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

时间:2016-10-23 01:44:19

标签: javascript jquery angularjs angularjs-ng-repeat angular-translate

以下是英语的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"正确显示值&#34;点击语言切换后立即选择赞助商名称&#34; (不需要刷新)。

问题:

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

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


问题是切换语言后,下拉菜单不会更改为所选语言,除非我刷新或更改视图并返回。如何解决此问题,使其像标签一样工作?

附件:

我的 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();

5 个答案:

答案 0 :(得分:2)

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

在您的代码中,通过执行此行var lang = $translate.use(newLang);进行一次请求,并在$http.get完成第二次调用,但如果在$http.get中调用$translate.use之前$translate.use已解决则已解决因为$translate中的请求尚未解决且$translateChangeSuccess服务尚未翻译这些翻译,因此不会在下拉列表中翻译内容。

您可以做的是在$translate上收听$rootScope事件(由$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; }); }); 服务发出),然后在此处理程序中进行ajax调用。

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

[增订]

$translate.use(localeId)

有关角度翻译模块的事件部分的详细说明,请结帐this link

每当您致电$translateChangeSuccess时,它都会在内部进行ajax调用,当此调用解决后,它会发出$scope.projectJSON事件,然后您发出请求,加载数据并更新$translate.use。<登记/> 唯一的事情是,当您刷新浏览器时,第一次触发此事件时,不会调用$translate.use

为此,您只需在页面重新加载时调用$scope.language.init

[增订]

将以下代码放在$translate.use(proposedLanguage || preferredLanguage); 函数的末尾。

Intent intent = new Intent(Intent.ACTION_VIEW);
Uri uri = Uri.parse(StaticMember.APP_DIR);
intent.setDataAndType(uri, "resource/folder");
context.startActivity(intent);

这可以解决您的问题。

答案 1 :(得分:1)

尝试使用promise模式:

$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;

答案 2 :(得分:0)

<强>旧

因为您使用的是异步函数,angular将无法立即识别更改。 下载文件后添加

$scope.$apply();

使角度重新扫描所有内容并应用更改。 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();,但我认为这已经包括在内了。

答案 3 :(得分:0)

你试过重装状态吗?

$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

答案 4 :(得分:0)

让我们一步一步地进行:
1)标签中的translate =“project.SPONSORINFO.MAIN”正确显示“选择赞助商名称”值,无需刷新 2)除非您刷新或更改视图并返回,否则下拉菜单不会更改为所选语言。

因此,翻译的切换实际上正在发挥作用。

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

首次进入页面时正在编译select选项,而在切换语言更改后不进行重新编译。因此,当您切换翻译时,您将检索文本,但是select选项元素不会被重新编译,因此在您下次重新输入/重新加载视图之前不会被动态翻译。

你有几种方法可以解决问题:
1)一旦翻译完成,程序性地刷新状态/路由。 (快速修复,但不好的方式)
2)编写一个角度指令,一旦检测到语言更改,就会重新编译该元素。 (更好的方法)

如何实现第二种解决方案的想法:

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>