我正在为一个使用原子设计组件的个人项目实现一个 i18n。到目前为止,我还没有遇到任何问题(而且我对 Angular 还很陌生),但在过去的几天里,我在这个话题上睡不着觉。事实证明,尝试提取 i18n 属性比迄今为止所值得的更麻烦。
问题
运行
ng extract-i18n
仅适用于 app.component.html
,不适用于子文件夹。
我也在准系统项目中尝试过这个:
ng new testProject
cd testProject
npm i @angular/localize
ng generate component testA
ng generate component components/testB
现在进行一些繁重的工作:
修改每个组件以包含简单的 i18n 声明。 我在各自的文件中使用了这些:
<p i18n="@@app">app</p> <!--@ src/app/app.component.html-->
<p i18n="@@testA">test-a works!</p> <!--@ src/app/test-a/test-a.component.html-->
<p i18n="@@testB">test-b works!</p> <!-- src/app/components/test-b.component.html-->
最后,运行
ng extract-i18n --outputPath="src/i18n"
,您应该会看到 src/i18n/messages.json
。但是,如果您注意到下面的内容,只有 @@app
被本地化,其余的都没有。
{
"locale": "en-US",
"translations": {
"app": "app"
}
}
但是
在寻找此问题的解决方案期间,我发现了这个演示项目。 正如您所注意到的,它还具有原子设计结构(或至少是它的一个版本)。
git clone https://github.com/PhraseApp-Blog/angular-i18n-2022
cd angular-i18n-2022
npm install
ng extract-i18n --outputPath="src/locale" --format="json"
唯一修改的文件是嵌套的
src/app/layout/navbar/navbar.component.html
来测试我的理论,其他所有内容都来自演示项目。
messages.json
输出:
{
"locale": "en-CA",
"translations": {
"1475737827206181859": "Demo companion app for\n <a href=\"{$PH}\">Phrase blog</a>\n post.\n <a href=\"{$PH_1}\">Made with Angular</a>.",
"navbar": "navbar",
"615967567956853879": "azcadea logo",
"7285274704628585281": "azcadea",
"2821179408673282599": "Home",
"1726363342938046830": "About",
"8856905278208146821": " {$ICU} ",
"7185053985224017078": "{VAR_PLURAL, plural, =0 {Sold out} =1 {Available at 1 outlet} other {Available at\n {INTERPOLATION} outlets}}",
"4481891408571585417": " Add to cart ",
"6223458566712133696": "Image of {$PH}"
}
}
总结
我尝试将我的配置文件与演示项目进行比较(
angular.json, package.json, tsconfig.app.json, tsconfig.json, tsconfig.spec.json
)。我已经反复检查了我能找到的所有可能的文档。我能发现的唯一显着差异是角度版本 latest vs 13.3.0
和模块版本 tsconfig.json
latest vs es2017/es2022
。
我的直觉表明这非常简单,我只是缺少一个属性/路径或一些声明来扫描子文件夹而不仅仅是应用程序文件夹。但我没有发现任何指示如何启用此功能。
如有任何建议或反馈,我们将不胜感激。
更新
正如 Volodymyr Mishyn 的评论所暗示的,该组件需要在其他组件/模块中引用,才能提取 i18n
因此:
我在顶部给出的创建新组件的示例不起作用,因为新生成的组件不会在任何地方自动引用,直到您将它们导入到相应的模块中。
我错过了什么:
在演示项目中,当您生成组件时,它会自动添加到
app.module.ts
,因此可以立即进行国际化。
在我的项目中,此行为不是默认行为,因此新组件已分离,因此未按预期进行 i18n 化。 这可能是由于 Angular 版本不同造成的,但这只是我的猜测。
令我困惑的是:
我在标头组件中将 i18n 添加到我的项目中
src/app/components/header/header.component.html
。
显然它已被引用和构建,但到目前为止提取还不起作用。我对这种行为的最好描述是提取管道被某种方式阻塞,但这是一个微弱的解释,没有什么价值。
您的组件在其他地方使用过吗? 就像其他组件或路由一样。
我得到的理论是,该问题与摇树有关。
您的组件在构建过程中不会在最终包中完成,因此不会提取 i18n。
我在我的宠物项目上尝试了这个理论
import { Routes } from '@angular/router';
import { HomeComponent } from './home/home.component';
import { FirstComponent } from './first/first.component';
// import { SecondComponent } from './second/second.component'; Commented this line
export const routes: Routes = [
{ path: '', redirectTo: '/home', pathMatch: 'full' },
{ path: 'home', component: HomeComponent },
{ path: 'first', component: FirstComponent },
// { path: 'second', component: SecondComponent }, and this line
{
path: '**',
redirectTo: '/home',
},
];
和跑步
ng extract-i18n --output-path src/locale
在结果文件中省略 SecondComponent 中的 i18n 字符串
所以尝试在某个地方使用你的组件。
老话题,但我的 Angular 18.0 项目也遇到了同样的问题。 我通过在 main.ts 中声明我的路由模块解决了这个问题
import { importProvidersFrom } from '@angular/core';
import { AppRoutingModule } from './app/app-routing.module';
bootstrapApplication(AppComponent, {
providers: [
importProvidersFrom(AppRoutingModule), // ==> Add this line
...
]
})