angularjs ng-重复来自不同 i18n 文件的下拉值

angularjs ng-repeat the dropdown values from different i18n files

这是一个示例 json 英语的 i18n 语言文件:

{
  "project": {
    "SPONSORINFO": {
      "MAIN" : "Select the Sponsor Name",
      "SPONSORLIST": [
        {"spons" :"SponsorName 1" },
        {"spons" :"SponsorName 2" }
      ]
    }
  }
}

这是我的 html 观点:

<div class="form-group" >
    <label for="form-field-select-1" translate="project.SPONSORINFO.MAIN">
    </label>
    <select class="form-control"  ng-model="myModel.sponsors">
       <option ng-repeat="s in projectJSON.project.SPONSORINFO.SPONSORLIST" value="{{s.spons}}">{{s.spons | translate}}</option>
    </select>
</div>

标签中的translate="project.SPONSORINFO.MAIN"在语言切换后立即正确显示值"Select the Sponsor Name"单击(不需要刷新)。

问题:

我在我的视图控制器中使用以下函数根据所选语言加载语言文件并将其传递到 $scope.projectJSON 以便我可以在我的 [=] 中的 ng-repeat 中调用它49=] 视图:

var lang = $translate.use();
$http.get('assets/i18n/'+lang+'.json').success(function(data) {
    $scope.projectJSON= data;
});


问题是切换语言后,下拉菜单不会更改为所选语言,除非我刷新或更改视图并返回。我该如何解决这个问题,使其像 label?

一样工作

附件:

我的 main.js 中的翻译全局配置如下所示:

app.config(['$translateProvider',
function ($translateProvider) {

    // prefix and suffix information  is required to specify a pattern
    // You can simply use the static-files loader with this pattern:
    $translateProvider.useStaticFilesLoader({
        prefix: 'assets/i18n/',
        suffix: '.json'
    });

    // Since you've now registered more then one translation table, angular-translate has to know which one to use.
    // This is where preferredLanguage(langKey) comes in.
    $translateProvider.preferredLanguage('en');

    // Store the language in the local storage
    $translateProvider.useLocalStorage();

}]);

我的翻译配置 mainCtrl.js:

app.controller('AppCtrl', ['$rootScope', '$scope', '$state', '$translate', 
function ($rootScope, $scope, $state, $translate) {

    $scope.language = {
        // Handles language dropdown
        listIsOpen: false,
        // list of available languages
        available: {
            'en': 'English',
            //'it_IT': 'Italiano',
            'de_DE': 'Deutsch'
        },
        // display always the current ui language
        init: function () {
            var proposedLanguage = $translate.proposedLanguage() || $translate.use();
            var preferredLanguage = $translate.preferredLanguage();
            // we know we have set a preferred one in app.config
            $scope.language.selected = $scope.language.available[(proposedLanguage || preferredLanguage)];
        },
        set: function (localeId, ev) {
            $translate.use(localeId);
            $scope.language.selected = $scope.language.available[localeId];
            $scope.language.listIsOpen = !$scope.language.listIsOpen;
        }
    };

    $scope.language.init();

因为您正在使用异步函数 angular 不会立即识别更改。 下载文件后添加

$scope.$apply();

要使 angular 重新扫描所有内容并应用更改。 Here 您可以阅读更多相关信息。

这对你来说意味着(@lascort 的$$阶段检查)

$http.get('assets/i18n/'+lang+'.json').success(function(data) {
$scope.projectJSON= data;
$translate.use(lang);
if (!$scope.$$phase)
    $scope.$apply();
  $translate.refresh();
});

编辑

但是官方资源建议使用他们的加载器而不是手动加载:Here

您正在使用 staticFilesLoader,因此请安装以下扩展:

bower install angular-translate-loader-static-files

然后在你的语言转换功能中:

$translateProvider.preferredLanguage(lang);

这应该有效(文档说)。也许你必须做一个 $scope.$apply(); 但我认为这已经包括在内了。

尝试使用承诺模式:

$http.get(..).then(function(response){..})

所以,看起来问题不在 ng-repeat 中,所以我会更改问题的标题。回到主题:

$http.get('assets/i18n/'+lang+'.json').then(function(response) {
    //check what exactly are you getting in the response
    //console.log(response)
    $scope.projectJSON = response;
});

我会检查 response 实际上,您可能需要做的是什么

$scope.projectJSON = response.data;

您尝试过重新加载状态吗?

$state.reload();

app.controller('AppCtrl', ['$rootScope', '$scope', '$state', '$translate', function ($rootScope, $scope, $state, $translate) {

$scope.language = {
    // Handles language dropdown
    listIsOpen: false,
    // list of available languages
    available: {
        'en': 'English',
        //'it_IT': 'Italiano',
        'de_DE': 'Deutsch'
    },
    // display always the current ui language
    init: function () {
        var proposedLanguage = $translate.proposedLanguage() || $translate.use();
        var preferredLanguage = $translate.preferredLanguage();
        // we know we have set a preferred one in app.config
        $scope.language.selected = $scope.language.available[(proposedLanguage || preferredLanguage)];
    },
    set: function (localeId, ev) {
        $translate.use(localeId);
        $scope.language.selected = $scope.language.available[localeId];
        $scope.language.listIsOpen = !$scope.language.listIsOpen;
    },
    uiReload: function(){
      $state.reload();
    }
};

$scope.language.init();
$scope.language.uiReload();    //call this for ui-router

让我们一步一步来:
1) 标签中的 translate="project.SPONSORINFO.MAIN" 正确显示值 "Select the Sponsor Name" 而无需刷新
2) 下拉菜单不会更改为 selected 语言,除非您刷新或更改视图并返回。

所以,翻译的切换实际上起作用了。

但为什么它不适用于下拉菜单? 我们可以注意到的一件事是 project.SPONSORINFO.MAIN 的标签是静态文本,而 s.spons 是基于值 return 的动态标签。

select 选项在进入页面时第一次被编译,并且在您切换语言更改后不会被重新编译。因此,当您切换翻译时,您会检索文本,但 select 选项元素不会被重新编译,因此不会在运行中翻译,直到您的下一个 reentering/reload 视图。

你解决问题的方法很少:
1) 翻译完成后以编程方式刷新 state/route。 (快速修复但方法不对)
2) 编写一个 angular 指令,在检测到语言更改后重新编译元素。 (更好的方法)

关于如何实现第二个解决方案的想法:

var lang = $translate.use();
$http.get('assets/i18n/'+lang+'.json').success(function(data) {
    $scope.projectJSON= data;
    $scope.newLanguage = $translate.use();
});

.directive('recompileLanguage', function($compile) {
  return {
    restrict: 'E',
    scope: {
      lang: '='
    },
    link: function(scope, element, attr) {
      $compile(element.contents())(scope);
      scope.$watch('lang', funcion (newValue, oldvalue) {
        $compile(element.contents())(scope);
      });
    }
  }
});

<select recompile-language lang={{newLanguage}}> </select>

您正在从翻译 json 文件迭代数组。此翻译 json 文件由 $translate 服务加载,您将无法访问已加载的内容,但您需要此 json 文件中的数据来迭代它,因此您必须制作您的自己请求获取这个数组。也许你不想,但你必须打 $http.get 电话。

在你的代码中,第一个请求是通过执行这一行 var lang = $translate.use(newLang); 发出的,第二个调用是由 $http.get 完成的,但是如果 $http.get 在调用 [=17= 之前得到解决] 已解决 它不会翻译下拉列表中的内容,因为 $translate.use 中的请求尚未解决并且 $translate 服务没有这些翻译要翻译。

您可以做的是在 $rootScope 上监听 $translateChangeSuccess 事件(由 $translate 服务发出),然后在此处理程序中进行 ajax 调用。

我已经在您的示例中测试了以下代码,它工作正常。

[更新]

$rootScope.$on('$translateChangeSuccess', function () {
  // Get new current new language
  var lang = $translate.use();
  $http.get('assets/i18n/'+lang+'.json').success(function(data) {
    $scope.projectJSON = data;
  });
});

有关 angular 翻译模块的事件部分的详细说明,请查看 this link

每当你调用 $translate.use(localeId) 时,它都会在内部进行 ajax 调用,当这个调用被解析时,它会发出 $translateChangeSuccess 事件,然后你发出请求,加载数据并更新 $scope.projectJSON.
唯一的事情是第一次触发这个事件,当你刷新浏览器时,当 $translate.use 没有被调用时。

为此,您只需在页面重新加载时调用 $translate.use 一次。

[更新]

将以下代码放在 $scope.language.init 函数的末尾。

$translate.use(proposedLanguage || preferredLanguage);

这应该可以解决您的问题。