你怎么能实现Angular国际化的数据库方法?

Kje*_*sen 17 internationalization angular

我在这里阅读了Angular i8n指南:https://angular.io/guide/i18n

我喜欢这些概念,使用文件中的标记和提示.

我不喜欢文本资源卡在一种奇怪的文件格式中,这种格式很容易翻译一次 - 但很难通过外部维护.

是否有一种相当直接的方式来使用Angular支持i8n的方式,但是用对数据库的调用替换静态文本文件 - 甚至是类似数据库生成的json文件?

Ben*_*idt 22

这是我处理i18n的方法,包括在从数据库加载翻译时使用ngx-translate.

在翻译方面,我的后端和前端是分开的.这些转换不是在角度构建或服务器包中提供的,而是通过HTTP休息调用来获取来自底层数据库的信息.所有翻译都在启动时加载,带入JSON结构,然后可以传递到前端,其中ngx-translate处理其余的..这是一个简单的事件顺序,可以成功地从数据库加载转换并使它们可以访问前端.

  1. 数据库中的安全翻译
  2. 在后端启动时加载转换(或实现重载机制,可能通过REST)
  3. 映射到键值对JSON对象
  4. 通过REST api使JSON对象可访问
  5. 前端通过此REST api加载JSON对象
  6. 使用ngx-translate在角度中使用JSON对象

好处

我稍后将详细介绍它的外观,并快速说明这种数据库休息方法带来的好处:

  • 所有翻译存储在一个地方(单个表)
  • 可以避免缺少某种语言的翻译(NULL检查)
  • 可以避免双键分配(PRIMARY KEY)
  • 可以运行时更新翻译
  • 翻译过程可以在项目之外进行(不需要更新项目结构中的文件)

让我们看看如何实现这一目标.

数据库

翻译通常包含基于翻译文件的简单键值对,这是我从未真正喜欢过的.因此,我将我的翻译保存在一个表中,其中包含我所拥有的每种语言的列和翻译列,例如类似于KEY | EN | FR | DE值的类似button.close | close | près | schließen.该键表示与普通文件中相同的键,但不是每种语言的单独文件,而是将翻译保存在单个列中.

后端映射到JSON对象

我喜欢立刻加载整个表格,以便立即为前端交付准备每种语言.这通常可以在后端启动时完成一次,结果可以保存在内存中以避免许多数据库调用.该表必须分成每个语言列的键值对JSON对象.然后,每个生成的语言对象都包含数据库键作为其键,并将翻译作为其值.

var EN = {
    ...
    "button.close": "close",
    ...
}
var FR = {
    ...
    "button.close": "près",
    ...
}
var DE = {
    ...
    "button.close": "schließen",
    ...
}
Run Code Online (Sandbox Code Playgroud)

这只是一个数组到对象的映射,根据服务器语言,它通常非常简单(如果需要,我可以共享node.js的代码).结果是一个JSON语言对象列表,每个对象都将其转换为键值对,然后可以访问它们.

HTTP休息呼叫

现在,翻译的格式与普通翻译文件的格式相同(键值对),只保留在内存中,而不是保存在文件中.通过对特定语言的简单HTTP api调用,您可以访问此列表,获取此语言的翻译对象并将其直接发送到前端.这是一个node.js明确的例子.

translationRouter.route('/:lang').get(function (request, response) {
    // load translation key-value-pair object for requested language
    response.send(translationService.getTranslations(request.params.lang));
});
Run Code Online (Sandbox Code Playgroud)

NGX-翻译

该方法NGX-翻译作品是非常直接的.翻译被加载到角度应用程序中,翻译键在应用程序中指定,然后由提供的语言的翻译值进行动态替换.正如其他人所说,它支持不同的加载翻译的方式,例如普通的旧翻译文件或自己实现的加载器,如HTTP加载器.这是一个简单的HTTP加载器,它通过REST调用加载翻译(见上文).

import { TranslateLoader } from '@ngx-translate/core';
import { Observable } from 'rxjs/Observable';
import { HttpClient } from '@angular/common/http';
import '../rxjs-operators';

export class TranslationLoader implements TranslateLoader {
    constructor(private http: HttpClient) { }

    getTranslation(lang: string): Observable<any> {
        return this.http.get("/api/translation/" + lang);
    }
}
Run Code Online (Sandbox Code Playgroud)

唯一的技巧是将此加载器指定为主加载器,可以在app.module中完成.这是一个使用上面的HTTP加载器的例子(也适用于AOT).

import { TranslateModule, TranslateLoader } from '@ngx-translate/core';
export function HttpLoaderFactory(http: HttpClient) {
    return new TranslationLoader(http);
}
...
@NgModule({
    imports: [..., 
        TranslateModule.forRoot({
            loader: {
                provide: TranslateLoader,
                useFactory: (HttpLoaderFactory),
                deps: [HttpClient]
            }
        }), ...]
})
Run Code Online (Sandbox Code Playgroud)

ngx-translate使用指定的TranslationLoader来获取其键值对,而不是请求文件,这正是我们通过休息调用提供的.十分简单.对于这种情况,可以指定要加载的语言,以及在未找到值的情况下使用后备语言.这是一个加载默认语言的翻译加上浏览器语言的翻译的示例.

// fallback language
this.translate.setDefaultLang('en');
// browser language
this.translate.use(this.translate.getBrowserLang());
Run Code Online (Sandbox Code Playgroud)

ngx-translate的文档非常好,有不同的方法可以使用它,例如通过服务,指令或管道,还可以参数化翻译.


附加信息

重新翻译

如福利列表中所述,您还可以在运行时重新加载翻译,这在捆绑应用程序以进行交付时可能更复杂.您可以简单地为管理员提供HTTP休息调用,该管理员执行与启动时完全相同的翻译加载过程.这样,翻译可以重新加载,重新映射并存储在存储器中.较新的页面请求将自动使用重新加载的翻译对象.

现场语言变化

某些使用ngx-translate的方法允许即时翻译开关(例如通过指令).这种方式加载角度不同的语言(通过简单的this.translate.use(lang)调用)将立即切换显示的翻译,而不重新编码页面或可见组件,这实际上非常整洁,但遗憾的是不适用于所有使用方式.

ngx-translate的限制

虽然ngx-translate非常容易使用,但它有限制.其中之一就是将ngx-translate指令与大多数角度材质指令结合使用,因为角度材质指令(例如按钮)将创建子树结构,而ngx-translate仅翻译第一个子节点上的键(at至少我认为它确实如此).所以使用起来很酷,但有时候有点棘手.



我想就是这样.我目前正在使用这种方法,我对它的结果非常满意.启动它是一项小工作,但一旦一切正在滚动它就会非常有用.