在某些情况下,需要提供多语言支持。 有时,在您正在构建的应用程序中提供对不同语言的支持,并为您的用户提供以不同习惯用法查看内容的可能性是一个好主意。 在本教程中,我将向您展示如何向任何AngularJS应用程序添加多语言支持。
我们将使用AngularJS构建一个需要多种语言支持的多语言支持的单页面应用程序,以便用户无需刷新页面即可立即在两种语言之间切换。 在这种情况下,我们需要对应用程序做更多的事情,包括翻译其文本,立即在不同语言之间切换或更改布局方向(从RTL到LTR)。
本文开发的所有代码都可以在GitHub上找到 。
环境设定
在我要向您展示的示例中,我将使用Bower和Gulp使我们的开发环境尽可能自动化和灵活。 如果尚未将它们安装在系统上,或者如果您从未在开发工作流程中使用过它们,则强烈建议您安装并开始更多地了解它们。 这是为此有用的文章列表:
首先,让我们通过在项目目录内的命令行中运行bower init
来设置Bower,我们将其称为multilingualwithangular
。 bower init
将以交互方式创建一个名为bower.json
的清单文件,该清单文件将包含有关项目的一些信息以及以前安装的前端依赖项的列表。
下一步是安装所需的初始软件包。
bower install angular angular-translate --save
让我们设置Gulp并安装这些基本软件包。 首先,我们需要运行命令npm init
并遵循一些简单的步骤来创建package.json
文件,其中将包含有关项目以及如何管理Node.js模块的一些信息。
接下来,我们将在项目中安装Gulp:
npm install gulp --save-dev
我们还需要JavaScript和Sass以及其他自动化工具的一些Gulp依赖项。
npm install gulp-sass gulp-uglify gulp-concat run-sequence browser-sync --save-dev
此时,我们必须在项目目录中创建一个空的gulpfile.js
配置文件。 它将用于定义我们的Gulp任务,例如JavaScript和Sass。 您可以在我的GitHub存储库中查看完整的配置文件 。
在JavaScript任务中,我们将在/js
目录中添加两个文件angular
和angular-translate
,以及主JavaScript文件。 然后,我们将它们连接在一起,并使用一个名为Uglify的 Node.js库来压缩和减小文件的大小。
'use strict';
var gulp = require('gulp');
var sass = require('gulp-sass');
var concat = require('gulp-concat');
var uglify = require('gulp-uglify');
var runSequence = require('run-sequence');
var browserSync = require('browser-sync');
gulp.task('js', function(){
return gulp.src([
'./bower_components/angular/angular.js',
'./bower_components/angular-translate/angular-translate.js',
'./js/app.js'])
.pipe(concat('app.min.js'))
.pipe(uglify())
.pipe(gulp.dest('./js'))
});
gulp.task('serve', function() {
browserSync({
server: {
baseDir: "./"
}
});
});
gulp.task('build', [], function() {
runSequence('js');
});
gulp.task('default', ['build'], function() {});
完成后,我们可以运行之前创建的gulp build
任务。 它会运行js
任务,然后生成一个/js/app.min.js
文件,该文件将包含在一个简单的HTML文件中。
<!DOCTYPE HTML>
<html>
<head>
<title>Multilingual AngularJS</title>
<meta charset="utf-8">
</head>
<body>
<script src="js/app.min.js"></script>
</body>
</html>
要在localhost环境中打开项目,请运行gulp serve
,然后将自动打开一个指向localhost:3000的浏览器选项卡。
使用Angular-Translate添加翻译
完成这些第一个配置任务后,就该迈出一步,为应用程序文本添加翻译支持了。 我们将阿拉伯语和英语作为主要语言。 就语法,语法和书写方向而言,它们是完全不同的语言(从右至左的阿拉伯语和从左至右的英语)。
angular-translate是一个AngularJS模块,可用于翻译文本。 它提供了许多有趣的功能,例如过滤器,指令和i18n数据的异步加载。
首先,让我们设置AngularJS并使用angular-translate
对其进行配置
// js/app.js
var app = angular.module('Multilingual', ['pascalprecht.translate']);
app.config(['$translateProvider', function($translateProvider) {
$translateProvider
.translations('ar', {
'HELLO': 'مرحبا'
})
.translations('en', {
'HELLO': 'Hello'
})
.preferredLanguage('ar');
}]);
然后,让我们稍微修改一下HMTL:
<html ng-app="Multilingual">
然后从命令行运行gulp build
来构建JavaScript文件中的新更改。 在前面的代码片段中,我们有:
- 创建了一个名为
Multilingual
的Angular模块。 - 作为
pascalprecht.translate
将angular-translate
模块作为依赖项注入到我们的应用程序中。 - 在
.config()
方法中注入了$translateProvider
。 - 使用
.translations()
方法并以诸如en
或ar
类的语言键作为第一个参数,以不同的语言注册翻译表。 - 使用
.preferredLanguage()
方法设置首选语言(这很重要,因为我们使用了不止一种语言,因此我们可以教您在首次加载时进行哪种angular-translate
)。
让我们看一个使用translate
滤镜进行angular-translate
的示例
<h2>{{ 'HELLO' | translate }}</h2>
视图中的过滤器太多,导致翻译指示文档中描述的手表表达式过多。 实现它的更好,更快的方法是使用translate
指令。 使用该指令的另一个原因是,用户可能会看到原始的{{ 'HELLO' | translate }}
在AngularJS加载模板之前,先{{ 'HELLO' | translate }}
。
我们可以使用伪指令的方法是将翻译ID传递为translate
伪指令的属性值。
<h2 translate="HELLO"></h2>
有时我们可能需要知道我们是否错过了一些翻译ID。 angular-translate-handler-log
提供了一个很好的方法,称为useMissingTranslationHandlerLog()
,可以帮助我们解决此问题,该方法会将警告信息记录在控制台中,以useMissingTranslationHandlerLog()
缺少的翻译ID。 要使用它,我们必须先安装它。 您可以使用Bower做到这一点:
bower install angular-translate-handler-log --save
然后,更新JavaScript Gulp任务:
gulp.task('js', function(){
return gulp.src([
'./bower_components/angular/angular.js',
'./bower_components/angular-translate/angular-translate.js',
// New file
'./bower_components/angular-translate-handler-log/angular-translate-handler-log.js',
'./js/app.js'])
.pipe(concat('app.min.js'))
.pipe(uglify())
.pipe(gulp.dest('./js'));
});
最后,直接在$translateProvider
上使用此方法运行gulp build
如下所示:
$translateProvider
.translations('ar', {
'HELLO': 'مرحبا'
})
.translations('en', {
'HELLO': 'Hello'
})
.preferredLanguage('ar')
.useMissingTranslationHandlerLog();
如果我们错过了HELLO
的翻译,由于这种方法,我们将收到一条警告消息,内容为“不存在HELLO的翻译”。
异步加载翻译文件
除了直接在.config()
方法中添加不同语言的翻译数据外,还有另一种方法可以异步和延迟地加载它们。 实际上, 有多种方法可以完成此任务 ,但是在本教程中,我们将仅使用angular-translate-loader-static-files
扩展名。
首先,我们需要使用Bower安装扩展:
bower install angular-translate-loader-static-files --save
安装完成后,我们需要使用扩展文件路径更新Gulp任务,然后运行gulp build
。
gulp.task('js', function(){
return gulp.src([
'./bower_components/angular/angular.js',
'./bower_components/angular-translate/angular-translate.js',
'./bower_components/angular-translate-handler-log/angular-translate-handler-log.js',
// New file
'bower_components/angular-translate-loader-static-files/angular-translate-loader-static-files.js',
'./js/app.js'])
.pipe(concat('app.min.js'))
.pipe(uglify())
.pipe(gulp.dest('./js'));
});
此时,我们需要创建/translations
目录并添加语言翻译文件。 结构将如下所示:
translations
├── ar.json
└── en.json
在ar.json
文件中,编写以下报告的内容:
{
"HELLO": "مرحبا",
"BUTTON_LANG_AR": "العربية",
"BUTTON_LANG_EN": "الإنجليزية",
"WELCOME_MESSAGE": "مرحباً في موقع AngularJS المتعدد اللغات"
}
相反,在en.json
文件中保存以下内容:
{
"HELLO": "Hello",
"BUTTON_LANG_AR": "Arabic",
"BUTTON_LANG_EN": "English",
"WELCOME_MESSAGE": "Welcome to the AngularJS multilingual site"
}
现在,我们可以使用useStaticFilesLoader
方法通过useStaticFilesLoader
方法告诉您使用特定模式加载哪些语言文件,进行angular-translate
:
prefix - specifies file prefix
suffix - specifies file suffix
以下是JavaScript文件的更改方式:
// js/app.js
app.config(['$translateProvider', function($translateProvider) {
$translateProvider
.useStaticFilesLoader({
prefix: '/translations/',
suffix: '.json'
})
.preferredLanguage('ar')
.useMissingTranslationHandlerLog();
}]);
如果要向文件添加前缀,可以使用前缀(在这种情况下为locale-
)重命名每个文件:
translations
├── locale-ar.json
└── locale-en.json
通过应用此更改,我们必须如下更新app.js
文件:
// js/app.js
app.config(['$translateProvider', function($translateProvider) {
$translateProvider
.useStaticFilesLoader({
prefix: '/translations/locale-',
suffix: '.json'
})
.preferredLanguage('ar')
.useMissingTranslationHandlerLog()
}]);
在这里, angular-translate
将我们的代码连接为{{prefix}}{{langKey}}{{suffix}}
,然后加载例如/translations/locale-en.json
文件。
在不同语言之间切换
到目前为止,我们已经看到了如何使用两种语言的文本翻译。 但是,我们仍然无法在运行时从浏览器切换到其他语言。 为此,我们需要为每种语言添加一个按钮以从中切换。
<div ng-controller="LanguageSwitchController">
<button ng-show="lang == 'en'" ng-click="changeLanguage('ar')" translate="BUTTON_LANG_AR"></button>
<button ng-show="lang == 'ar'" ng-click="changeLanguage('en')" translate="BUTTON_LANG_EN"></button>
</div>
我们还可以创建一些$rootScope
属性,并在我们的HTML代码上使用它们,以便在首次加载时设置初始布局方向和lang
属性,并在以后每次更改语言时将其绑定。
// js/app.js
app.run(['$rootScope', function($rootScope) {
$rootScope.lang = 'en';
$rootScope.default_float = 'left';
$rootScope.opposite_float = 'right';
$rootScope.default_direction = 'ltr';
$rootScope.opposite_direction = 'rtl';
}])
angular-translate
提供了一种方便的方法,称为use
,它use
一个参数并根据传递的参数为我们设置语言。 此外,我们将收听$translateChangeSuccess
事件,该事件在翻译更改成功后就会触发,以确保语言已更改。 然后,我们可以根据所选语言修改$rootScope
属性:
// js/app.js
app.controller('LanguageSwitchController', ['$scope', '$rootScope', '$translate',
function($scope, $rootScope, $translate) {
$scope.changeLanguage = function(langKey) {
$translate.use(langKey);
};
$rootScope.$on('$translateChangeSuccess', function(event, data) {
var language = data.language;
$rootScope.lang = language;
$rootScope.default_direction = language === 'ar' ? 'rtl' : 'ltr';
$rootScope.opposite_direction = language === 'ar' ? 'ltr' : 'rtl';
$rootScope.default_float = language === 'ar' ? 'right' : 'left';
$rootScope.opposite_float = language === 'ar' ? 'left' : 'right';
});
}]);
并将以下更改应用于标记:
<html lang="{{ lang }}" ng-app="Multilingual">
在我的标题为使用Helper类进行DRY和Scale CSS的文章中 ,您可以看到另一个示例,这些示例在HTML中将这些方向属性用作Helper类:
<div class="text-{{ default_float }}"></div>
记住语言
至此,我们已经建立了切换语言功能,并且可以更改语言以使用我们最喜欢的语言。 下一步是让应用程序记住我们选择的语言,因此,下次启动它时,我们不必再次切换到该语言。
我们将使用浏览器localStorage教会应用程序记住该语言,以存储所选语言,并且为此目的,我们将使用angular-translate-storage-local扩展名。 您可以想象,下一步是安装它。 我们将与Bower一起做:
bower install angular-translate-storage-local --save
运行此命令,我们还将安装angular-cookies
和angular-translate-storage-cookie
作为依赖项。 安装完成后,我们需要使用运行gulp build
的新文件来更新Gulp任务:
gulp.task('js', function(){
return gulp.src([
'./bower_components/angular/angular.js',
'./bower_components/angular-translate/angular-translate.js',
'./bower_components/angular-translate-handler-log/angular-translate-handler-log.js',
'bower_components/angular-translate-loader-static-files/angular-translate-loader-static-files.js',
// New files
'./bower_components/angular-cookies/angular-cookies.js',
'./bower_components/angular-translate-storage-cookie/angular-translate-storage-cookie.js',
'./bower_components/angular-translate-storage-local/angular-translate-storage-local.js',
'./js/app.js'])
.pipe(concat('app.min.js'))
.pipe(uglify())
.pipe(gulp.dest('./js'));
});
使用此代码后,接下来的步骤是:
- 添加
ngCookies
作为依赖项。 - 告诉
$translateProvider
通过useLocalStorage()
使用localStorage
我们需要进行以下操作:
var app = angular.module('Multilingual', [
'pascalprecht.translate',
'ngCookies'
]);
app.config(['$translateProvider', function($translateProvider) {
$translateProvider
.useStaticFilesLoader({
prefix: '/translations/',
suffix: '.json'
})
.preferredLanguage('ar')
.useLocalStorage()
.useMissingTranslationHandlerLog()
}]);
angular-translate
将存储我们由preferredLanguage()
使用键NG_TRANSLATE_LANG_KEY
设置的初始语言。 它将在浏览器localStorage中将语言分配为其值,然后在每次用户切换语言时对其进行更新。 当用户打开应用程序时, angular-translate
将从localStorage检索它 。
使用布局方向
我们已经到达演示部分。 如果您使用书写方向相同的两种语言(例如英语和法语),则配置已完成。 如果语言方向之一是RTL,而另一方向是LTR,则我们需要做一些额外的工作来调整某些布局方案。
假设这是LTR语言(英语)的CSS代码:
.media-image { padding-right: 1rem; }
对于RTL语言,以上代码应镜像为padding-left
而不是padding-right
:
.media-image { padding-left: 1rem; }
但是,这根本不是一个好习惯,因为它很耗时,并且涉及到代码重复:
[lang='ar'] .media-image {
padding-right: 0;
padding-left: 1rem;
}
为了解决这个问题,我们需要编写一些CSS代码,并以有效,自动化和动态的方式支持RTL语言和LTR。 使用这种方法,我们不必重复或覆盖CSS规则。 我鼓励您阅读我的文章“ 使用Sass和Grunt管理RTL CSS”,以了解有关此技术以及如何在项目中使用它的更多信息。
在本教程中,我们将使用Gulp来实现它,并添加一个使用ltr-app.scss
和rtl-app.scss
的Sass任务。 除了导入其中的特定于方向的变量外,我们还将导入主Sass文件:
gulp.task('sass', function () {
return gulp.src(['./sass/ltr-app.scss', './sass/rtl-app.scss'])
.pipe(sass())
.pipe(gulp.dest('./css'));
});
// Update the build task with sass
gulp.task('build', [], function() {
runSequence('js', 'sass');
});
sass/ltr-app.scss
文件应如下所示:
// LTR language directions
$default-float: left;
$opposite-float: right;
$default-direction: ltr;
$opposite-direction: rtl;
@import 'style';
这是sass/rtl-app.scss
的代码:
// RTL language directions
$default-float: right;
$opposite-float: left;
$default-direction: rtl;
$opposite-direction: ltr;
@import 'style';
最后,这是sass/style.scss
的示例:
body { direction: $default-direction; }
.column { float: $default-float; }
.media-image { padding-#{$opposite-float}: 1rem; }
使用所有这些代码之后,您可以运行gulp build
,Sass任务将生成两个文件。 css/rtl-app.css
将具有下面列出的代码:
/* css/rtl-app.css */
body { direction: rtl; }
.column { float: right; }
.media-image { padding-left: 1rem; }
css/ltr-app.css
文件将包含以下报告的内容:
/* css/ltr-app.css */
body { direction: ltr; }
.column { float: left; }
.media-image { padding-right: 1rem; }
下一步也是最后一步,就是根据当前语言动态使用这些生成的文件。 我们将使用$rootScope
的default_direction
属性在首次加载期间设置方向,然后在更改语言时将其绑定。
<link ng-href="css/{{ default_direction }}-app.css" rel="stylesheet">
结论
如我们所见,在涉及AngularJS转换时,使用angular-translate是可行的方法。 它提供了许多方便的过滤器,指令和有趣的工具。 我们以许多不同的方式介绍了翻译过程,并探讨了如何在两种语言之间切换。 我们还讨论了如何在用户浏览器存储中存储选定的语言,以及如何与CSS配合使用以使表示层对语言指示的响应速度更快。
希望您喜欢本教程。 我已经为本文创建了GitHub存储库, 您可以在此处查看代码 。 请在下面的部分中随意分享您的评论。
From: https://www.sitepoint.com/multilingual-support-for-angularjs/