如何翻译Angular-UI-Bootstrap datepicker?

时间:2021-10-02 11:05:25

The documentation for the datepicker (Angle-UI-BootStrap) reports:

datepicker(Angle-UI-BootStrap)报告的文档:

Everything is formatted using the date filter and thus is also localized.

所有内容都使用日期过滤器进行格式化,因此也是本地化的。

Checking the documentation for the date filter can have access to the concept of i18n and i10n for AngularJs. However, the two approaches which are provided, can not be used in my application. The two approaches are:

检查日期过滤器的文档可以访问AngularJs的i18n和i10n的概念。但是,提供的两种方法不能在我的应用程序中使用。这两种方法是:

  1. Pre-bundled rule sets
  2. 预捆绑规则集

  3. Including locale js script in index.html page
  4. 在index.html页面中包含locale js脚本

In my application, I check the language of the client after he had performed login. So my index.html page is already created and configured.

在我的应用程序中,我在登录后检查客户端的语言。所以我的index.html页面已经创建并配置好了。

There is no other way to translate the datepicker? A dynamically way... something like changing a value of the $scope that alters the interface performing the translation of the component?

没有其他方法来翻译datepicker?动态方式......比如更改$ scope的值,改变执行组件转换的接口的值?

Here's a plunker demonstrating the approach of introducing in the index.html the translation for pt-BR.

这里有一个吸收者,展示了在index.html中引入pt-BR翻译的方法。

Update: I asked this question in an issue of the Angle-UI-Bootstrap, and here is the response I received from @bekos:

更新:我在Angle-UI-Bootstrap问题中问过这个问题,这是我从@bekos收到的回复:

@ThCC The real problem is that you cannot change your $locale during runtime, or at least I don't know of a way to do this. Even if you solve the problem with the datepicker, you will still have problem in every other filter that is locale dependent, like currency. I think it is better to ask a more general question in the AngularJS issues.

@ThCC真正的问题是你不能在运行时更改$ locale,或者至少我不知道如何做到这一点。即使您使用datepicker解决了问题,您仍然会遇到与区域设置相关的所有其他过滤器(例如货币)的问题。我认为最好在AngularJS问题中提出更一般的问题。

If anyone has another solution is always welcome. If I get a solution I will return here.

如果有人有另一个解决方案,总是欢迎。如果我得到解决方案,我会回到这里。

3 个解决方案

#1


9  

Someone said [The real problem is that you cannot change your $locale during runtime]. In fact you can. You can see a working plunker here.

有人说[真正的问题是你不能在运行时改变你的$ locale]。事实上你可以。你可以在这里看到一个工作的plunker。

#2


2  

You can create your own directive like this:

您可以像这样创建自己的指令:

angular
    .module('myApp.common')
    .directive('datepickerPopupWrap', datepickerPopupWrap);

datepickerPopupWrap.$inject = ['$rootScope'];

function datepickerPopupWrap($rootScope, $compile) {

    return {

        restrict: 'A',
        require: 'ngModel',

        link: function($scope, $element, attrs, ngModel) {
            // Force popup rerender whenever locale changes
            $rootScope.$on('localeChanged', ngModel.$render);
        }
    };

}

The directive name must be datepickerPopupWrap, so it's executed together with the default ui-bootstrap directive that renders the popup.

指令名称必须是datepickerPopupWrap,因此它与呈现弹出窗口的默认ui-bootstrap指令一起执行。

Then, whenever you change the locale with angular-dynamic-locale, do this:

然后,每当您使用angular-dynamic-locale更改语言环境时,请执行以下操作:

tmhDynamicLocale.set(languageKey).then(function() {

    // Set the language in angular-translate
    $translate.use(languageKey);

    // Broadcast the event so datepickers would rerender
    $rootScope.$broadcast('localeChanged');
});

#3


1  

I was not happy using the given approaches, so I figured out this one by using angular-translate and the possibility, to overwrite the angular-ui-bootstrap-templates like this (Source from ui-bootstrap-tpls.js):

我对使用给定的方法感到不满意,所以我通过使用angular-translate和覆盖angular-ui-bootstrap-templates这样的可能性来解决这个问题(来自ui-bootstrap-tpls.js的源代码):

For uib/template/datepicker/day.html:

angular.module("uib/template/datepicker/day.html", []).run(["$templateCache", function($templateCache) {
    $templateCache.put("uib/template/datepicker/day.html",
        "<table class=\"uib-daypicker\" role=\"grid\" aria-labelledby=\"{{::uniqueId}}-title\" aria-activedescendant=\"{{activeDateId}}\">\n" +
        "  <thead>\n" +
        "    <tr>\n" +
        "      <th><button type=\"button\" class=\"btn btn-default btn-sm pull-left uib-left\" ng-click=\"move(-1)\" tabindex=\"-1\"><i class=\"glyphicon glyphicon-chevron-left\"></i></button></th>\n" +
        "      <th colspan=\"{{::5 + showWeeks}}\"><button id=\"{{::uniqueId}}-title\" role=\"heading\" aria-live=\"assertive\" aria-atomic=\"true\" type=\"button\" class=\"btn btn-default btn-sm uib-title\" ng-click=\"toggleMode()\" ng-disabled=\"datepickerMode === maxMode\" tabindex=\"-1\"><strong>{{ title | uppercase | localizeMonth }}</strong></button></th>\n" +
        "      <th><button type=\"button\" class=\"btn btn-default btn-sm pull-right uib-right\" ng-click=\"move(1)\" tabindex=\"-1\"><i class=\"glyphicon glyphicon-chevron-right\"></i></button></th>\n" +
        "    </tr>\n" +
        "    <tr>\n" +
        "      <th ng-if=\"showWeeks\" class=\"text-center\"></th>\n" +
        "      <th ng-repeat=\"label in ::labels track by $index\" class=\"text-center\"><small aria-label=\"{{::label.full}}\">{{ ('DAY_' + label.abbr | uppercase) | translate}}</small></th>\n" +
        "    </tr>\n" +
        "  </thead>\n" +
        "  <tbody>\n" +
        "    <tr class=\"uib-weeks\" ng-repeat=\"row in rows track by $index\">\n" +
        "      <td ng-if=\"showWeeks\" class=\"text-center h6\"><em>{{ weekNumbers[$index] }}</em></td>\n" +
        "      <td ng-repeat=\"dt in row\" class=\"uib-day text-center\" role=\"gridcell\"\n" +
        "        id=\"{{::dt.uid}}\"\n" +
        "        ng-class=\"::dt.customClass\">\n" +
        "        <button type=\"button\" class=\"btn btn-default btn-sm\"\n" +
        "          uib-is-class=\"\n" +
        "            'btn-info' for selectedDt,\n" +
        "            'active' for activeDt\n" +
        "            on dt\"\n" +
        "          ng-click=\"select(dt.date)\"\n" +
        "          ng-disabled=\"::dt.disabled\"\n" +
        "          tabindex=\"-1\"><span ng-class=\"::{'text-muted': dt.secondary, 'text-info': dt.current}\">{{::dt.label}}</span></button>\n" +
        "      </td>\n" +
        "    </tr>\n" +
        "  </tbody>\n" +
        "</table>\n" +
        "");
}]);

For uib/template/datepicker/month.html:

angular.module("uib/template/datepicker/month.html", []).run(["$templateCache", function($templateCache) {
    $templateCache.put("uib/template/datepicker/month.html",
        "<table class=\"uib-monthpicker\" role=\"grid\" aria-labelledby=\"{{::uniqueId}}-title\" aria-activedescendant=\"{{activeDateId}}\">\n" +
        "  <thead>\n" +
        "    <tr>\n" +
        "      <th><button type=\"button\" class=\"btn btn-default btn-sm pull-left uib-left\" ng-click=\"move(-1)\" tabindex=\"-1\"><i class=\"glyphicon glyphicon-chevron-left\"></i></button></th>\n" +
        "      <th><button id=\"{{::uniqueId}}-title\" role=\"heading\" aria-live=\"assertive\" aria-atomic=\"true\" type=\"button\" class=\"btn btn-default btn-sm uib-title\" ng-click=\"toggleMode()\" ng-disabled=\"datepickerMode === maxMode\" tabindex=\"-1\"><strong>{{title}}</strong></button></th>\n" +
        "      <th><button type=\"button\" class=\"btn btn-default btn-sm pull-right uib-right\" ng-click=\"move(1)\" tabindex=\"-1\"><i class=\"glyphicon glyphicon-chevron-right\"></i></button></th>\n" +
        "    </tr>\n" +
        "  </thead>\n" +
        "  <tbody>\n" +
        "    <tr class=\"uib-months\" ng-repeat=\"row in rows track by $index\">\n" +
        "      <td ng-repeat=\"dt in row\" class=\"uib-month text-center\" role=\"gridcell\"\n" +
        "        id=\"{{::dt.uid}}\"\n" +
        "        ng-class=\"::dt.customClass\">\n" +
        "        <button type=\"button\" class=\"btn btn-default\"\n" +
        "          uib-is-class=\"\n" +
        "            'btn-info' for selectedDt,\n" +
        "            'active' for activeDt\n" +
        "            on dt\"\n" +
        "          ng-click=\"select(dt.date)\"\n" +
        "          ng-disabled=\"::dt.disabled\"\n" +
        "          tabindex=\"-1\"><span ng-class=\"::{'text-info': dt.current}\">{{ ('MONTH_' + dt.label | uppercase) | translate }}</span></button>\n" +
        "      </td>\n" +
        "    </tr>\n" +
        "  </tbody>\n" +
        "</table>\n" +
        "");
}]);

You also need to extend your language file by (this is for the german language):

您还需要扩展您的语言文件(这是针对德语):

, 'MONTH_JANUARY':                  'Januar'
, 'MONTH_FEBRUARY':                 'Februar'
, 'MONTH_MARCH':                    'März'
, 'MONTH_APRIL':                    'April'
, 'MONTH_MAY':                      'May'
, 'MONTH_JUNE':                     'June'
, 'MONTH_JULY':                     'July'
, 'MONTH_AUGUST':                   'August'
, 'MONTH_SEPTEMBER':                'September'
, 'MONTH_OCTOBER':                  'October'
, 'MONTH_NOVEMBER':                 'November'
, 'MONTH_DECEMBER':                 'December'

And since the current month of the datepicker is orignally rendered as {{title}} provied by scope.title = dateFilter(this.activeDate, this.formatDayTitle); (line 2216 in ui-bootstrap-tpls.js), you have to load a filter to localize the current month (Thanks to this post):

并且由于datepicker的当前月份由scope.title = dateFilter(this.activeDate,this.formatDayTitle)提供{{title}}。 (ui-bootstrap-tpls.js中的第2216行),你必须加载一个过滤器来本地化当前月份(感谢这篇文章):

/* global app */
app.filter('localizeMonth', function($interpolate)
{
    return function (input)
    {
        return input
            .replace(/JANUARY/g,   $interpolate('{{ \'MONTH_JANUARY\'   | translate}}'))
            .replace(/FEBRUARY/g,  $interpolate('{{ \'MONTH_FEBRUARY\'  | translate}}'))
            .replace(/MARCH/g,     $interpolate('{{ \'MONTH_MARCH\'     | translate}}'))
            .replace(/APRIL/g,     $interpolate('{{ \'MONTH_APRIL\'     | translate}}'))
            .replace(/MAY/g,       $interpolate('{{ \'MONTH_MAY\'       | translate}}'))
            .replace(/JUNE/g,      $interpolate('{{ \'MONTH_JUNE\'      | translate}}'))
            .replace(/JULY/g,      $interpolate('{{ \'MONTH_JULY\'      | translate}}'))
            .replace(/AUGUST/g,    $interpolate('{{ \'MONTH_AUGUST\'    | translate}}'))
            .replace(/SEPTEMBER/g, $interpolate('{{ \'MONTH_SEPTEMBER\' | translate}}'))
            .replace(/OCTOBER/g,   $interpolate('{{ \'MONTH_OCTOBER\'   | translate}}'))
            .replace(/NOVEMBER/g,  $interpolate('{{ \'MONTH_NOVEMBER\'  | translate}}'))
            .replace(/DECEMBER/g,  $interpolate('{{ \'MONTH_DECEMBER\'  | translate}}'))
        ;
    };
});

I think this solution is at least as ugly as the other hacks that were invented here, but you don't have to trigger redraws or similar things by yourself.

我认为这个解决方案至少和这里发明的其他黑客一样丑陋,但你不必自己触发重绘或类似的东西。

#1


9  

Someone said [The real problem is that you cannot change your $locale during runtime]. In fact you can. You can see a working plunker here.

有人说[真正的问题是你不能在运行时改变你的$ locale]。事实上你可以。你可以在这里看到一个工作的plunker。

#2


2  

You can create your own directive like this:

您可以像这样创建自己的指令:

angular
    .module('myApp.common')
    .directive('datepickerPopupWrap', datepickerPopupWrap);

datepickerPopupWrap.$inject = ['$rootScope'];

function datepickerPopupWrap($rootScope, $compile) {

    return {

        restrict: 'A',
        require: 'ngModel',

        link: function($scope, $element, attrs, ngModel) {
            // Force popup rerender whenever locale changes
            $rootScope.$on('localeChanged', ngModel.$render);
        }
    };

}

The directive name must be datepickerPopupWrap, so it's executed together with the default ui-bootstrap directive that renders the popup.

指令名称必须是datepickerPopupWrap,因此它与呈现弹出窗口的默认ui-bootstrap指令一起执行。

Then, whenever you change the locale with angular-dynamic-locale, do this:

然后,每当您使用angular-dynamic-locale更改语言环境时,请执行以下操作:

tmhDynamicLocale.set(languageKey).then(function() {

    // Set the language in angular-translate
    $translate.use(languageKey);

    // Broadcast the event so datepickers would rerender
    $rootScope.$broadcast('localeChanged');
});

#3


1  

I was not happy using the given approaches, so I figured out this one by using angular-translate and the possibility, to overwrite the angular-ui-bootstrap-templates like this (Source from ui-bootstrap-tpls.js):

我对使用给定的方法感到不满意,所以我通过使用angular-translate和覆盖angular-ui-bootstrap-templates这样的可能性来解决这个问题(来自ui-bootstrap-tpls.js的源代码):

For uib/template/datepicker/day.html:

angular.module("uib/template/datepicker/day.html", []).run(["$templateCache", function($templateCache) {
    $templateCache.put("uib/template/datepicker/day.html",
        "<table class=\"uib-daypicker\" role=\"grid\" aria-labelledby=\"{{::uniqueId}}-title\" aria-activedescendant=\"{{activeDateId}}\">\n" +
        "  <thead>\n" +
        "    <tr>\n" +
        "      <th><button type=\"button\" class=\"btn btn-default btn-sm pull-left uib-left\" ng-click=\"move(-1)\" tabindex=\"-1\"><i class=\"glyphicon glyphicon-chevron-left\"></i></button></th>\n" +
        "      <th colspan=\"{{::5 + showWeeks}}\"><button id=\"{{::uniqueId}}-title\" role=\"heading\" aria-live=\"assertive\" aria-atomic=\"true\" type=\"button\" class=\"btn btn-default btn-sm uib-title\" ng-click=\"toggleMode()\" ng-disabled=\"datepickerMode === maxMode\" tabindex=\"-1\"><strong>{{ title | uppercase | localizeMonth }}</strong></button></th>\n" +
        "      <th><button type=\"button\" class=\"btn btn-default btn-sm pull-right uib-right\" ng-click=\"move(1)\" tabindex=\"-1\"><i class=\"glyphicon glyphicon-chevron-right\"></i></button></th>\n" +
        "    </tr>\n" +
        "    <tr>\n" +
        "      <th ng-if=\"showWeeks\" class=\"text-center\"></th>\n" +
        "      <th ng-repeat=\"label in ::labels track by $index\" class=\"text-center\"><small aria-label=\"{{::label.full}}\">{{ ('DAY_' + label.abbr | uppercase) | translate}}</small></th>\n" +
        "    </tr>\n" +
        "  </thead>\n" +
        "  <tbody>\n" +
        "    <tr class=\"uib-weeks\" ng-repeat=\"row in rows track by $index\">\n" +
        "      <td ng-if=\"showWeeks\" class=\"text-center h6\"><em>{{ weekNumbers[$index] }}</em></td>\n" +
        "      <td ng-repeat=\"dt in row\" class=\"uib-day text-center\" role=\"gridcell\"\n" +
        "        id=\"{{::dt.uid}}\"\n" +
        "        ng-class=\"::dt.customClass\">\n" +
        "        <button type=\"button\" class=\"btn btn-default btn-sm\"\n" +
        "          uib-is-class=\"\n" +
        "            'btn-info' for selectedDt,\n" +
        "            'active' for activeDt\n" +
        "            on dt\"\n" +
        "          ng-click=\"select(dt.date)\"\n" +
        "          ng-disabled=\"::dt.disabled\"\n" +
        "          tabindex=\"-1\"><span ng-class=\"::{'text-muted': dt.secondary, 'text-info': dt.current}\">{{::dt.label}}</span></button>\n" +
        "      </td>\n" +
        "    </tr>\n" +
        "  </tbody>\n" +
        "</table>\n" +
        "");
}]);

For uib/template/datepicker/month.html:

angular.module("uib/template/datepicker/month.html", []).run(["$templateCache", function($templateCache) {
    $templateCache.put("uib/template/datepicker/month.html",
        "<table class=\"uib-monthpicker\" role=\"grid\" aria-labelledby=\"{{::uniqueId}}-title\" aria-activedescendant=\"{{activeDateId}}\">\n" +
        "  <thead>\n" +
        "    <tr>\n" +
        "      <th><button type=\"button\" class=\"btn btn-default btn-sm pull-left uib-left\" ng-click=\"move(-1)\" tabindex=\"-1\"><i class=\"glyphicon glyphicon-chevron-left\"></i></button></th>\n" +
        "      <th><button id=\"{{::uniqueId}}-title\" role=\"heading\" aria-live=\"assertive\" aria-atomic=\"true\" type=\"button\" class=\"btn btn-default btn-sm uib-title\" ng-click=\"toggleMode()\" ng-disabled=\"datepickerMode === maxMode\" tabindex=\"-1\"><strong>{{title}}</strong></button></th>\n" +
        "      <th><button type=\"button\" class=\"btn btn-default btn-sm pull-right uib-right\" ng-click=\"move(1)\" tabindex=\"-1\"><i class=\"glyphicon glyphicon-chevron-right\"></i></button></th>\n" +
        "    </tr>\n" +
        "  </thead>\n" +
        "  <tbody>\n" +
        "    <tr class=\"uib-months\" ng-repeat=\"row in rows track by $index\">\n" +
        "      <td ng-repeat=\"dt in row\" class=\"uib-month text-center\" role=\"gridcell\"\n" +
        "        id=\"{{::dt.uid}}\"\n" +
        "        ng-class=\"::dt.customClass\">\n" +
        "        <button type=\"button\" class=\"btn btn-default\"\n" +
        "          uib-is-class=\"\n" +
        "            'btn-info' for selectedDt,\n" +
        "            'active' for activeDt\n" +
        "            on dt\"\n" +
        "          ng-click=\"select(dt.date)\"\n" +
        "          ng-disabled=\"::dt.disabled\"\n" +
        "          tabindex=\"-1\"><span ng-class=\"::{'text-info': dt.current}\">{{ ('MONTH_' + dt.label | uppercase) | translate }}</span></button>\n" +
        "      </td>\n" +
        "    </tr>\n" +
        "  </tbody>\n" +
        "</table>\n" +
        "");
}]);

You also need to extend your language file by (this is for the german language):

您还需要扩展您的语言文件(这是针对德语):

, 'MONTH_JANUARY':                  'Januar'
, 'MONTH_FEBRUARY':                 'Februar'
, 'MONTH_MARCH':                    'März'
, 'MONTH_APRIL':                    'April'
, 'MONTH_MAY':                      'May'
, 'MONTH_JUNE':                     'June'
, 'MONTH_JULY':                     'July'
, 'MONTH_AUGUST':                   'August'
, 'MONTH_SEPTEMBER':                'September'
, 'MONTH_OCTOBER':                  'October'
, 'MONTH_NOVEMBER':                 'November'
, 'MONTH_DECEMBER':                 'December'

And since the current month of the datepicker is orignally rendered as {{title}} provied by scope.title = dateFilter(this.activeDate, this.formatDayTitle); (line 2216 in ui-bootstrap-tpls.js), you have to load a filter to localize the current month (Thanks to this post):

并且由于datepicker的当前月份由scope.title = dateFilter(this.activeDate,this.formatDayTitle)提供{{title}}。 (ui-bootstrap-tpls.js中的第2216行),你必须加载一个过滤器来本地化当前月份(感谢这篇文章):

/* global app */
app.filter('localizeMonth', function($interpolate)
{
    return function (input)
    {
        return input
            .replace(/JANUARY/g,   $interpolate('{{ \'MONTH_JANUARY\'   | translate}}'))
            .replace(/FEBRUARY/g,  $interpolate('{{ \'MONTH_FEBRUARY\'  | translate}}'))
            .replace(/MARCH/g,     $interpolate('{{ \'MONTH_MARCH\'     | translate}}'))
            .replace(/APRIL/g,     $interpolate('{{ \'MONTH_APRIL\'     | translate}}'))
            .replace(/MAY/g,       $interpolate('{{ \'MONTH_MAY\'       | translate}}'))
            .replace(/JUNE/g,      $interpolate('{{ \'MONTH_JUNE\'      | translate}}'))
            .replace(/JULY/g,      $interpolate('{{ \'MONTH_JULY\'      | translate}}'))
            .replace(/AUGUST/g,    $interpolate('{{ \'MONTH_AUGUST\'    | translate}}'))
            .replace(/SEPTEMBER/g, $interpolate('{{ \'MONTH_SEPTEMBER\' | translate}}'))
            .replace(/OCTOBER/g,   $interpolate('{{ \'MONTH_OCTOBER\'   | translate}}'))
            .replace(/NOVEMBER/g,  $interpolate('{{ \'MONTH_NOVEMBER\'  | translate}}'))
            .replace(/DECEMBER/g,  $interpolate('{{ \'MONTH_DECEMBER\'  | translate}}'))
        ;
    };
});

I think this solution is at least as ugly as the other hacks that were invented here, but you don't have to trigger redraws or similar things by yourself.

我认为这个解决方案至少和这里发明的其他黑客一样丑陋,但你不必自己触发重绘或类似的东西。