【问题标题】:How to use xi18n (AOT) within server side rendering (universal) in angular如何在服务器端渲染(通用)中以角度使用 xi18n(AOT)
【发布时间】:2018-06-11 17:05:45
【问题描述】:

我想为多语言 Angular 应用程序提供服务,同时使用服务器端渲染来实现 SEO 和性能。 为此,我目前有以下情况:

package.json 脚本:

"build:ssr": "npm run build:client-and-server-bundles && npm run webpack:server",
"serve:ssr": "node dist/server",
"build:client-and-server-bundles": "npm run build-i18n && ng run my-web:server",
"webpack:server": "webpack --config webpack.server.config.js --progress --colors",
"build-i18n:de": "LOCALE=de && npm run build-i18n:locale",
"build-i18n:en": "ng build --output-path=dist/browser/en --aot --prod --base-href /en/ --i18n-locale=en",
"build-i18n": "npm run build-i18n:en && npm run build-i18n:de"

server.ts:

// Locale to get best language match
import { Locales } from 'locale';

app.engine('html', ngExpressEngine({
  bootstrap: AppServerModuleNgFactory,
  providers: [
    provideModuleMap(LAZY_MODULE_MAP)
  ]
}));

app.set('view engine', 'html');
app.set('views', join(DIST_FOLDER, 'browser'));

const supportedLanguages = ['de', 'en'];

for (const language of supportedLanguages) {
  // Server languages static files from /browser
  app.get('/' + language + '/*.*', express.static(join(DIST_FOLDER, language, 'browser'))); // todo

  // All languaged regular routes use the Universal engine
  app.get('/' + language + '/*', (req, res) => {
    console.log(language);
    res.render(language + '/index', {req});
  });
}

我的问题是我只得到了正确的 index.html 和正确的 base-href,但没有从 .xlf 文件中获得正确的翻译文本(只有组件 HTML 中的那些)。我在 dist/server 中只有一个 main.js。 使用 xi18n 和 AOT,我得到 dist/browser/de 和 dist/browser/en。 我找不到任何教程或示例能够将 xi18n 和 angular 的服务器端渲染结合起来。

我的 angular.json 有以下 architect 条目:

"server": {
          "builder": "@angular-devkit/build-angular:server",
          "options": {
            "outputPath": "dist/server",
            "main": "src/main.server.ts",
            "tsConfig": "src/tsconfig.server.json"
          }
        }

如果有人能帮我解决这个问题,那就太好了。

我的角度版本是:6.0.3

提前谢谢你。

斋月

【问题讨论】:

    标签: angular internationalization angular-universal


    【解决方案1】:

    这是我为韩文做的:

    package.json

    "build:client-and-server-bundles-ko": "ng build --prod --base-href=/ko --deploy-url=/ko/ --output-path=dist/ko/browser --i18n-file=src/locale/messages.ko.xlf --i18n-locale=ko --i18n-format=xlf  && ng run rendercore-www:server --outputPath=dist/ko/server",
    "build:client-and-server-bundles-staging-ko": "ng build --prod --base-href=/ko --deploy-url=/ko/ --output-path=dist/ko/browser --i18n-file=src/locale/messages.ko.xlf --i18n-locale=ko --i18n-format=xlf  --configuration=staging && ng run rendercore-www:server:staging --outputPath=dist/ko/server",
    "build:client-and-server-bundles-prod-ko": "ng build --prod --base-href=/ko --deploy-url=/ko/ --output-path=dist/ko/browser --i18n-file=src/locale/messages.ko.xlf --i18n-locale=ko --i18n-format=xlf  --configuration=production && ng run rendercore-www:server:production --outputPath=dist/ko/server",
    "build:ssr-ko": "npm run build:client-and-server-bundles-ko && npm run webpack:server-ko",
    "build:ssr-staging-ko": "npm run build:client-and-server-bundles-staging-ko  && npm run webpack:server-ko",
    "build:ssr-prod-ko": "npm run build:client-and-server-bundles-prod-ko  && npm run webpack:server-ko",
    "webpack:server-ko": "webpack --config webpack.server.config.js --env.lang=ko --progress --colors",
    

    server-ko.ts

    // These are important and needed before anything else
    import "zone.js/dist/zone-node";
    import "reflect-metadata";
    import { enableProdMode } from "@angular/core";
    import * as express from "express";
    import { join } from "path";
    
    // Faster server renders w/ Prod mode (dev mode never needed)
    enableProdMode();
    
    // Express server
    const app = express();
    
    const PORT = process.env.PORT || 4000;
    // const DIST_FOLDER = join(process.cwd(), 'dist');
    const DIST_FOLDER = join(process.cwd(), "");  //here..i changed
    
    // * NOTE :: leave this as require() since this file is built Dynamically from webpack
    const { AppServerModuleNgFactory, LAZY_MODULE_MAP } = require("./dist/ko/server/main");//here..i changed add ko
    
    // Express Engine
    import { ngExpressEngine } from "@nguniversal/express-engine";
    // Import module map for lazy loading
    import { provideModuleMap } from "@nguniversal/module-map-ngfactory-loader";
    
    app.engine(
        "html",
        ngExpressEngine({
            bootstrap: AppServerModuleNgFactory,
            providers: [provideModuleMap(LAZY_MODULE_MAP)]
        })
    );
    
    //here..i changed
    app.use(function(req, res, next) { 
        if (req.url.slice(0, 4) === "/ko/") {
          req.url = req.url.slice(3);
        }
        next();
    });
    
    app.set("view engine", "html");
    app.set("views", join(DIST_FOLDER, "browser"));
    
    // Server static files from /browser
    app.get("*.*", express.static(join(DIST_FOLDER, "browser")));
    
    // All regular routes use the Universal engine
    app.get("*", (req, res) => {
        console.log(`GET: ${req.originalUrl}`);
        res.render("index", {
          req: req,
          res: res
        });
    });
    
    // Start up the Node server
    app.listen(PORT, () => {
        console.log(`Node server listening on http://localhost:${PORT}`);
    });
    

    webpack.server.config.js

    const path = require("path");
    const webpack = require("webpack");
    
    module.exports = env => {
        //console.log(env);
        let langWithDash = env == undefined ? "" : "-" + env.lang;
        let langWithSlash = env == undefined ? "" : "/" + env.lang;
        return {
          entry: { server: "./server" + langWithDash + ".ts" },
          resolve: { extensions: [".js", ".ts"] },
          target: "node",
          mode: "none",
          // this makes sure we include node_modules and other 3rd party libraries
          externals: [/node_modules/],
          output: {
            path: path.join(__dirname, "dist" + langWithSlash),
            filename: "[name].js"
          },
          module: {
            rules: [{ test: /\.ts$/, loader: "ts-loader" }]
          },
          plugins: [
            // Temporary Fix for issue: https://github.com/angular/angular/issues/11580
            // for 'WARNING Critical dependency: the request of a dependency is an expression'
            new webpack.ContextReplacementPlugin(
              /(.+)?angular(\\|\/)core(.+)?/,
              path.join(__dirname, "src"), // location of your src
              {} // a map of your routes
            ),
            new webpack.ContextReplacementPlugin(/(.+)?express(\\|\/)(.+)?/, path.join(__dirname, "src"), {})
          ]
        };
    };
    

    使用npm run build:ssr-ko

    然后它将在 dist 文件夹下创建一个子文件夹,如下所示:

    /dist/ko/xxxxx

    您必须从 Web 服务器重写 URL。我使用 IIS,所以这是一个 IIS 示例:

    <rule name="Lang-EN" stopProcessing="true">
        <match url="^en[\/].*?" />
        <action type="Rewrite" url="dist/en/server.js" />
    </rule>
    
    <rule name="L51ang-KO" stopProcessing="true">
        <match url="^ko[\/].*" />
        <action type="Rewrite" url="dist/ko/server.js" />
    </rule>
    

    此外,/assets URL 也会出错,因为当前的 Angular 存在错误。

    即使您使用base-hrefdeploy-url,仍然有一些HTML 会有/assets 路径。

    所以我试试这个:

    <rule name="Asset Redirect" stopProcessing="true">
        <match url="^assets\/.*" />
        <action type="Rewrite" url="dist/en/server.js" appendQueryString="true" />
    </rule>
    

    还有一个提示,如果客户端访问站点的/,重定向到他们的浏览器语言设置:

    <rule name="Redirect To KO"  stopProcessing="true">
        <match url="^$" />
            <conditions>
              <add input="{HTTP_ACCEPT_LANGUAGE}" pattern="^ko" />
            </conditions>
        <action type="Redirect" url="{R:0}/ko/home" appendQueryString="true" />
    </rule>
    

    如果您想添加其他语言,请再次执行此步骤。

    我的构建脚本如下所示:

    cd www
    rmdir /S /Q dist
    call npm i 
    call npm run build:ssr-staging-en || exit /b -1
    call npm run build:ssr-staging-ko || exit /b -1
    call npm run build:ssr-staging-ja || exit /b -1
    

    build en ko ja,那么它会创建这个:

    /dist/ko/server.js
    /dist/en/server.js
    /dist/ja/server.js
    

    只需将其上传到网络服务器,然后正确设置重写。

    希望你能理解。谢谢。

    【讨论】:

      猜你喜欢
      • 2017-07-06
      • 1970-01-01
      • 1970-01-01
      • 2018-09-09
      • 1970-01-01
      • 1970-01-01
      • 2020-10-20
      • 2018-04-19
      • 2020-01-24
      相关资源
      最近更新 更多