【问题标题】:How to localize data coming from the backend with ngx-translate如何使用 ngx-translate 本地化来自后端的数据
【发布时间】:2020-10-16 12:45:00
【问题描述】:

我正在使用 ngx-translate 构建一个 Angular 应用程序。它运作良好。现在我开始有来自我的后端(firebase)的数据,我将为此进行翻译。

从模型中显示本地化数据的正确方法是什么?我还没有确定数据格式,所以要么是这样的:

{
  'title_fr': 'mon titre',
  'title_en': 'my title',
  'title_de': 'mein Titel',
  'description_fr' : '....'
  //...
}

类似:

{
   title: {'fr':'mon titre', 'en': 'my title', 'de': 'mein Titel'}
   description: { 'fr': 'ma description', /*...*/}
}

我不知道如何显示它们:

  1. 我将有很多 ngFor 迭代这些项目的 observable,如果我可以避免必须映射每个数据,那就太好了
  2. 当语言改变时,我还需要显示正确的翻译

你会推荐我什么?

【问题讨论】:

    标签: angular localization internationalization ngx-translate


    【解决方案1】:

    如果您能够定义可以从后端获取的数据,那么您可能可以制作如下数据结构,

    {
        "dataLocalization": [{
                                "locale": "fr",
                                "title": "mon titre",
                                "description":"ma description"
                            },
                            {
                                "locale": "en",
                                "title": "my title",
                                "description":"my description"
                            }]
    }
    

    然后你可以通过数组dataLocalization中的findIndex方法找到你的locale,并使用它的title和description值

    【讨论】:

    • 这样检查,如果您有任何疑问,请告诉我,如果您觉得这个有用,请将其标记为正确,并请点赞
    • 是的,但是如果用户切换语言,这将如何改变
    • 您将从您的 Firebase 接收到的这些数据存储在某个地方吗?每当用户更改您可能正在使用 translate.use 的更改订阅的语言时,您需要再次检查此数组并根据此数组更改值
    • 是的,但是处理来自 ngx-translate 的更改 + 来自 firebase 的更改的最佳方法是什么?
    【解决方案2】:

    @ngx-translate/http-loader 库允许使用 http 加载翻译。

    下面是我如何在我开发的应用程序中使用ngx-translatehttp-loader 的示例。

    我已经制作了下面代码的工作stackblitz(可用here):

    定义 i18n 字符串的数据结构

    在该示例中,对于每种语言,都有一个 url,可以通过以下格式检索翻译数据 (json):

    {
      welcome: "Welcome",
      subscription_msg: "Subscribe now"
    }
    

    为每种支持的语言创建一个网络服务

    考虑一个支持 3 种语言的应用程序:enptfr

    我通常为每种语言设置一个网址。每个 url 返回一个带有 key - value 对的 json,其中键是我在前端使用的标签,值是我想以该语言向用户显示的消息。

    在该示例中,我创建了 3 个模拟 url,每种语言的翻译如下:

    英文 - 模拟网址:https://run.mocky.io/v3/33f736b0-e73a-499e-8a50-01e66041d634

    {
      welcome: "Welcome",
      subscription_msg: "Subscribe now"
    }
    

    葡萄牙语 - 模拟网址:https://run.mocky.io/v3/db1e37da-342e-4918-8ce2-bd30aa12fe79

    {
      welcome: "Bem-vindo",
      subscription_msg: "Inscreva-se gratuitamente"
    }
    

    法语 - 模拟网址:https://run.mocky.io/v3/6960c960-ea66-42a0-87f1-f34568ecb740

    {
      welcome: "Bienvenue",
      subscription_msg: "Abbonez-vous"
    }
    

    为了在前端输出subscription_msg,我使用ngx-translate这样的语法:

    {{ 'subscription_msg' | translate}}
    

    安装@ngx-translate/http-loader

    假设ngx-translate已经安装,这是安装http-loader的命令:

    npm install @ngx-translate/http-loader --save
    

    创建您自己的 TranslationLoader

    我们需要实现TranslationLoader 接口。它只有一个方法 (getLanguage()) 负责加载当前语言的 i18n 消息映射。

    Bellow 是我们称为TranslationHttpLoader 的简单实现。更改语言时调用它:

    export class TranslationHttpLoader implements TranslateLoader {
      constructor(private httpClient: HttpClient) {}
    
      public getTranslation(lang: string): Observable<Object> {
        if (lang == null) {
          lang == "en";
        }
    
        let urls = {
          en: "https://run.mocky.io/v3/33f736b0-e73a-499e-8a50-01e66041d634",
          pt: "https://run.mocky.io/v3/db1e37da-342e-4918-8ce2-bd30aa12fe79",
          fr: "https://run.mocky.io/v3/6960c960-ea66-42a0-87f1-f34568ecb740"
        };
    
        let observer = new Observable(observer => {
          this.httpClient.get(urls[lang]).subscribe(
            data => {
              observer.next(data);
              observer.complete();
            }
          );
        });
        return observer;
      }
    }
    

    配置翻译提供者

    app.module.ts 中我们应该定义一个HttpLoaderFactory

    export function HttpLoaderFactory(httpClient: HttpClient) {
      return new TranslationHttpLoader(httpClient);
    }
    

    并将其与提供的TranslateLoader关联:

    @NgModule({
      imports: [
        BrowserModule,
        FormsModule,
        HttpClientModule,
        TranslateModule.forRoot({
          loader: {
            provide: TranslateLoader,
            useFactory: HttpLoaderFactory,
            deps: [HttpClient]
          }
        })
      ],
      declarations: [AppComponent],
      bootstrap: [AppComponent]
    })
    export class AppModule {}
    

    测试 - 更改语言并显示本地化消息

    测试

    • 我们创建了一个简单的组件,它有一个&lt;select&gt; 和一个(change) 事件处理程序,其中语言作为选项。
    • 要输出本地化字符串,我们使用ngx-translate 语法{{ 'key_in_json_file' | translate }}

    app.component.html

    <div>
        <label>Language</label>
        <select (change)="changeLanguage($event)">
        <option value="en">English</option>
        <option value="pt">Português</option>
        <option value="fr">Français</option>
      </select>
    
        <p>
            {{'welcome' | translate}}.
        </p>
        <p>
            {{'subscription_msg' | translate}}
        </p>
    </div>
    

    (change) 事件发生时,我们所要做的就是调用translate.use(lang)。我们的加载器将在提供的 url 中检索所选语言的数据并将其提供给ngx-translate

    app.component.ts

    export class AppComponent {
      defaultLang: string = "en";
    
      constructor(private translateService: TranslateService) {}
      ngOnInit() {
        this.translateService.use(this.defaultLang);
      }
      changeLanguage(event) {
        let lang = (event.target as HTMLInputElement).value;
        this.translateService.use(lang);
      }
    }
    

    输出预览

    后续步骤

    可以在此处提供的代码中进行一些增强,例如:

    • 使用translateService.getBrowserLang()在用户首次访问时检测浏览器语言
    • 将用户当前语言存储在本地存储或其他持久存储中。
    • 调整TranslationHttpLoader,使其可以使用每种语言的默认令牌离线工作(在移动应用程序中尤其有用)。

    可以在此堆栈闪电战中看到上述代码:https://stackblitz.com/edit/angular-ivy-pwcrvy?file=src/app/translation-http-loader.ts

    【讨论】:

    • 非常感谢您的完整回答,但我不确定它是否适用于我。我从firebase获取数据,所以我需要使用ngfire包来访问我的数据(它允许自动管理后端和前端之间的同步,允许离线工作然后同步,......),所以我不能使用HttpLoader :(。另外,我不确定关键是什么?这实际上是关于在我的后端拥有本地化的业务数据,就像tripadvisor 有本地化的描述一样。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-26
    • 2019-02-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多