我看到angular6为其组件实现了i18n,并且通过使用i18n可以将html国际化,但是您可以对打字稿做同样的事情吗?我有两个特定领域
一个有趣的图表:-能够举个例子
exampleData = {
valueBox: {
text: '<span style="font-size: 32px">%pie-total-value</span> <br/> Example',
placement: 'center',
fontWeight: 'normal'
},
}
非常感谢您的时间和答复。
答案 0 :(得分:3)
在Angular 9中,您可以像这样使用全局$ localize函数:
func loadImageFromDiskWith(fileName: String) -> UIImage? {
let documentDirectory = FileManager.SearchPathDirectory.documentDirectory
let userDomainMask = FileManager.SearchPathDomainMask.userDomainMask
let paths = NSSearchPathForDirectoriesInDomains(documentDirectory, userDomainMask, true)
if let dirPath = paths.first {
let imageUrl = URL(fileURLWithPath: dirPath).appendingPathComponent(fileName)
let image = UIImage(contentsOfFile: imageUrl.path)
return image
}
return nil
}
请注意:
$localize`String to translate`
答案 1 :(得分:2)
直到现在(@angular/language-service v7.2
)都无法通过库的API来完成。
以下是我的解决方法(感谢his good post on GitHub和thank @BrunoBruzzano for the link的fredrikredflag):
src/app/i18n.service.ts
:
import {Injectable} from "@angular/core";
import {Xliff2} from '@angular/compiler';
// You can also import {Xliff} or {Xtb} from "@angular/compiler"
declare const require;
const content = require('raw-loader!../i18n/messages.fa.xlf');
@Injectable({
providedIn: 'root'
})
export class I18nService {
private readonly xliff: any = new Xliff2().load(content, '');
get(key: string): string {
return this.xliff.i18nNodesByMsgId[key][0].value;
}
}
i18n伪组件(仅用于messages.xlf
文件中的自动生成翻译):
src/app/i18n/i18n.component.ts
(无关紧要。只需要存在即可)。
import {Component} from '@angular/core';
@Component({templateUrl: './i18n.component.html'})
export class I18nComponent {}
src/app/i18n/i18n.component.html
( 不要忘记使用ID! )
<p i18n="@@newVersionAlert">New version available. Load New Version?</p>
别忘了在I18nComponent
中声明@NgModule
。
用法(在运行ng xi18n ...
并翻译之后):
在您的组件中:
...
import {I18nService} from './i18n.service';
...
constructor(private i18nService: I18nService, ...) { ... }
sampleUsage() {
confirm(this.t('newVersionAlert'));
}
/**
* translate
*/
private t(i18nId: string) {
return this.i18nService.get(i18nId);
}
...
在构建之前翻译i18n.service.ts
的实用程序脚本:
(此要求:require('raw-loader!../i18n/messages.fa.xlf')
需要进行翻译以匹配所需的语言环境。)
PreBuild/prebuild.ts
:
import {Xliff2} from "@angular/compiler";
// You can also import {Xliff} or {Xtb} from "@angular/compiler" depending of your case.
const fs = require('fs');
const path = require('path');
const localeId = process.argv[2];
if (localeId === undefined) throw new Error(`No language specified.\nUsage: node ${path.basename(__filename)} <locale-id${'>'}`);
const content = fs.readFileSync(`src/i18n/messages.${localeId}.xlf`, 'utf8');
const xliff = new Xliff2().load(content, '');
fs.writeFileSync(i18nServiceFilePath,
fs.readFileSync(i18nServiceFilePath, 'utf8')
.replace(/(raw-loader!\.\.\/i18n\/messages\.)\w{2}(\.xlf)/, `$1${xliff.locale}$2`)
);
PreBuild/tsconfig.json
:
{
"compilerOptions": {
"outDir": "./build",
"lib": [
"es2018",
"dom"
],
"module": "commonjs",
"moduleResolution": "node",
"target": "es6",
"typeRoots": [
"../node_modules/@types"
]
},
"files": [
"prebuild.ts"
]
}
package.json
:
...
"scripts": {
"compile-pre-build": "tsc -p PreBuild/tsconfig.json --pretty",
"pre-build": "node PreBuild/build/prebuild.js",
...
...
用法:
(一次npm run compile-pre-build
之后:)
npm run pre-build -- fa
或
npm run pre-build -- en
这将编辑i18n.service.ts
。
答案 2 :(得分:0)
您可以使用Transloco库执行此操作:https://ngneat.github.io/transloco/。
然后像这样在Typescript文件中获取翻译:
this.translocoService.translate('hello');
答案 3 :(得分:-1)
您可以扩展“ ng serve | build”过程,以便在.ts中完成i18n翻译的“ AOT补全”
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent {
title = 'i18n-ts-demo-ng';
title2 = '@@my.test.header';
}
并将其翻译为构建过程
//create file i18n-plugin.ts in root
import { I18NTransformer } from './i18n';
import { AngularCompilerPlugin } from '@ngtools/webpack';
function findAngularCompilerPlugin(webpackCfg): AngularCompilerPlugin | null {
return webpackCfg.plugins.find(plugin => plugin instanceof AngularCompilerPlugin);
}
// The AngularCompilerPlugin has nog public API to add transformations, user private API _transformers instead.
function addTransformerToAngularCompilerPlugin(acp, transformer): void {
acp._transformers = [transformer, ...acp._transformers];
}
export default {
pre() {
// This hook is not used in our example
},
// This hook is used to manipulate the webpack configuration
config(cfg) {
// Find the AngularCompilerPlugin in the webpack configuration
const angularCompilerPlugin = findAngularCompilerPlugin(cfg);
if (!angularCompilerPlugin) {
console.error('Could not inject the typescript transformer: Webpack AngularCompilerPlugin not found');
return;
}
addTransformerToAngularCompilerPlugin(angularCompilerPlugin, I18NTransformer);
return cfg;
},
post() {
// This hook is not used in our example
}
};
//create file i18n.ts in root
import * as ts from 'typescript';
// TODO move to config
const RequireAlli18NKeys = false; // if true onda all 18n keys must be found othervse error is thrown;
// Read translations
import { Xliff, Node } from '@angular/compiler';
const fs = require('fs');
const path = require('path');
let localeId: string; // hr || en ...
let i18nLocale = 0; // 0 - parameter not found | 1 - parameter is fount so next is locale string (hr, ...)
// parse parameters
process.argv.forEach(pParam => {
console.log('param:' + pParam);
// get Locale is using: ng serve ...
if (pParam.startsWith('--configuration=')) {
localeId = pParam.replace('--configuration=', '');
console.log('Locale:' + localeId);
}
// Has to be before code down
if (i18nLocale === 1) {
i18nLocale = 2;
localeId = pParam;
console.log('Locale:' + localeId);
}
// Get locale if using: ng build --prod --i18n-locale en ...
if (pParam.startsWith('--i18n-locale')) {
i18nLocale = 1;
localeId = pParam.replace('--config--i18n-locale ', '')
}
});
// Load translation
// tslint:disable-next-line:max-line-length
if (localeId === undefined) { throw new Error(`No language specified.\nUsage: ng serve --configuration=hr --aot --plugin ~dist/out-tsc/i18n-plugin.js`); }
const content = fs.readFileSync(`src/translate/messages.${localeId}.xlf`, 'utf8');
const xliff = new Xliff().load(content, '');
export const I18NTransformer = <T extends ts.Node>(context: ts.TransformationContext) => {
return (rootNode: ts.SourceFile) => {
function visit(node: ts.Node): ts.Node {
if (
rootNode.fileName.includes('node_modules')
|| !rootNode.fileName.includes('.ts')
// || ts.isToken(node)
) {
return ts.visitEachChild(node, visit, context);
}
if (ts.isStringLiteral(node)) {
// teplace @@ with translation
if (node.text.includes('@@')) {
// take key for translatioc
const tSourceKey = node.text;
const tI18NKey = node.text.replace('@@', '');
// find key
const tTranslation: any = xliff.i18nNodesByMsgId[tI18NKey];
if (tTranslation) {
// let t1 = tTranslation[0];
// let tLocaleStr = t1.toString(); //tTranslation[0].value;
const tLocaleStr = tTranslation[0].value;
console.log(ConsoleColor.BgCyan, 'i18n key: ', ConsoleColor.Reset, tI18NKey + '=> translation : ' + tLocaleStr);
const tNew2 = node.text.replace(tSourceKey, tLocaleStr);
return ts.createStringLiteral(tNew2);
}
const tMessage = 'ERROR! No translation for key: ' + tI18NKey + ', source:' + rootNode.fileName;
console.log(ConsoleColor.BgRed, tMessage, ConsoleColor.Reset);
if (RequireAlli18NKeys) {
throw new Error(tMessage);
}
}
}
return ts.visitEachChild(node, visit, context);
}
return ts.visitNode(rootNode, visit);
};
};
class ConsoleColor {
static Reset = '\x1b[0m';
static Bright = '\x1b[1m';
static Dim = '\x1b[2m';
static Underscore = '\x1b[4m';
static Blink = '\x1b[5m';
static Reverse = '\x1b[7m';
static Hidden = '\x1b[8m';
static FgBlack = '\x1b[30m';
static FgRed = '\x1b[31m';
static FgGreen = '\x1b[32m';
static FgYellow = '\x1b[33m';
static FgBlue = '\x1b[34m';
static FgMagenta = '\x1b[35m';
static FgCyan = '\x1b[36m';
static FgWhite = '\x1b[37m';
static BgBlack = '\x1b[40m';
static BgRed = '\x1b[41m';
static BgGreen = '\x1b[42m';
static BgYellow = '\x1b[43m';
static BgBlue = '\x1b[44m';
static BgMagenta = '\x1b[45m';
static BgCyan = '\x1b[46m';
static BgWhite = '\x1b[47m';
}
在终端开始位置:tsc --skipLibCheck --module umd -w
ng serve --configuration = hr --aot --plugin〜dist / out-tsc / i18n-plugin.js
完整示例在https://github.com/Emanuel3003/i18n-ts-demo-ng
致谢