【问题标题】:Angular i18 internationalization, language change programmaticallyAngular i18 国际化,以编程方式更改语言
【发布时间】:2018-11-26 15:17:08
【问题描述】:

通过此链接,我尝试在我的 Angular 6 应用程序中实现 i18 国际化,以便在我的 html 模板中用英语和意大利语翻译一些文本和日期时间。

https://next.angular.io/guide/i18n

我知道这个功能分为三个阶段:

  1. 定义翻译文本。没问题,我创建了一个文件夹 src/locale 文件夹,其中包含 2 个文件 messages.en.xlf(和 message.it.xlf);这是一个 en 版本的示例。

    你好 i18n! (zh-CN) 此示例的介绍标题 用户欢迎
  2. 用适当的标签将此文本链接到 html 页面,这里也没有问题,我的 app.translations.html 中有我的示例标签。

    你好 i18n!

现在,我阅读了在启动期间本地化应用程序的方式(3.阶段)(在 Angular.json 文件中进行一些编辑并使用配置选项启动 ng serve);但是,我会以编程方式更改应用程序的语言,而不是这样做。换句话说,我想要一个命令,例如

SwitchAppLanguage('en')

例如,用户可以通过按钮自行更改,或者应用程序可以读取浏览器默认语言来执行此操作。我该怎么做?

编辑

我尝试以这种方式编辑我的 angular.json 文件

"configurations": {
  "production": {
     "i18nFile": "src/locale/messages.it.xlf",
     "i18nFormat": "xlf",
     "i18nLocale": "it",
(...)

而且,在ng buildng serve 之后,我希望看到意大利语文本,但它没有发生(并且应用程序启动并正确运行)。我做错了什么?

【问题讨论】:

  • 没有这样的东西。该应用程序在构建时本地化。如果您需要两种语言,则需要构建两次,并从您的 Web 服务器提供两个不同的应用程序。要更改语言,您需要加载其他应用程序。
  • 不可能定义2种语言并告诉Angular“切换到这种语言”吗?我好像很奇怪,你确定吗?在这种情况下,用户在应用使用过程中无法选择语言,对吗?
  • 是的,我确定。是,对的。它写在您链接到的页面中,逐字逐句:当您使用 AOT 编译器进行国际化时,您必须为每种语言预先构建一个单独的应用程序包,并根据服务器端语言检测或 url 参数提供适当的包.
  • 一旦 Ivy 出现,您将能够拥有一个适用于所有语言的应用程序,但您仍需要重新加载应用程序以切换语言。可以使用 ngx-translate,它有这个功能(但效率较低,还有其他限制)
  • window.location.href = urlOfTheOtherApp;.

标签: angular internationalization


【解决方案1】:

我以这种方式为开发模式解决了这个问题。 也许有人可以从中受益。

这只是一个临时解决方案,直到 Angular 在 ivy i18n 中提供此功能。

缺点:只能在语言文件生成为 JSON 时才能完成 :-(

polyfills.ts:

import { loadTranslations } from '@angular/localize';
import { isDevMode } from '@angular/core';

// All translation objects: must be json files for runtime-conditions! (XLF not supported)
import * as fr from "./i18n/messages.fr.json";
import * as nl from "./i18n/messages.nl.json";
import * as en from "./i18n/messages.json";


// Non-official translation loader to switch languages at runtime in development mode
if(isDevMode()){
  let translations = {};
  let lang = localStorage.getItem("lang");
  if(lang === "fr"){
    translations = fr;
  } else if (lang === "nl"){
    translations = nl;
  } else{
    translations = en;
  }

  // load translations at runtime
  loadTranslations(translations['default']['translations']);
}

【讨论】:

    【解决方案2】:

    所以如果你使用 JIT,你可以使用 webpacks loader 来热交换语言文件:

    ma​​in.ts

    import { enableProdMode } from '@angular/core';
    import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
    
    import { AppModule } from './app/app.module';
    import { environment } from './environments/environment';
    import { getTranslationProviders } from './app/providers/i18n.provider';
    import { LocaleService } from './app/services/locale.service';
    
    if ( environment.production ) {
      enableProdMode();
    }
    
    const locale = new LocaleService();
    locale.getLocale().then( ( localeValue ) => {
      getTranslationProviders( localeValue ).then( providers => {
        platformBrowserDynamic().bootstrapModule( AppModule, { providers } )
          .catch( err => console.log( err ) );
      } );
    } );
    

    i18n.provider

    import { TRANSLATIONS, TRANSLATIONS_FORMAT } from '@angular/core';
    declare const require;
    
    export function getTranslationProviders( locale: string ): Promise<any[]> {
    
      // Get the locale id as arugment or from the global
      //
      const localeValue = locale || document[ 'locale' ] as string;
    
    
      // return no providers if fail to get translation file for locale
      //
      const noProviders: Object[] = [];
    
      // No locale or AU, doesn't require translation
      //
      if ( !localeValue || localeValue === 'au' ) {
        return Promise.resolve( noProviders );
      }
      try {
        const translations = require( `raw-loader!../../locale/messages.${ localeValue }.xlf` );
        return Promise.resolve( [
          { provide: TRANSLATIONS, useValue: translations },
          { provide: TRANSLATIONS_FORMAT, useValue: 'xlf' }
        ] );
      } catch ( error ) {
        console.error( error );
        return Promise.resolve( noProviders );
      }
    
    }
    
    

    local.service

    import { WindowRef } from 'app/services/windowRef.service';
    import { environment } from 'environments/environment';
    
    
    @Injectable()
    
    export class LocaleService {
      _locale: string;
      set locale( val: string ) {
        this._locale = val;
      }
      get locale() {
        return this._locale;
      }
    
    
      constructor() {
        this.setLocale();
      }
    
      setLocale() {
        const winRef = new WindowRef();
    
        this.locale = ( environment.countryLookup[ document.location.hostname ] || 'au' ).toLowerCase();
    
        const match = document.location.search.match( /au|nz/ );
    
        if ( match ) {
          this.locale = match.shift();
        }
        // store locale in document
        //
        winRef.nativeWindow.document.locale = this.locale;
      }
    
      getLocale(): Promise<string> {
        return Promise.resolve( this.locale );
      }
    
    }
    
    

    您将不得不对其进行一些重构以匹配您的项目,但我希望您能理解要点。 在 Ivy 支持正确的语言切换之前,这可能是一个解决方案。

    【讨论】:

      猜你喜欢
      • 2012-01-13
      • 2022-08-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多