i18next.js
1 year ago
i18next.min.js
1 year ago
i18nextHttpBackend.js
1 year ago
i18nextHttpBackend.min.js
1 year ago
i18nextSprintfPostProcessor.js
1 year ago
i18nextSprintfPostProcessor.min.js
1 year ago
ng-i18next.js
1 year ago
ng-i18next.min.js
1 year ago
ng-i18next.js
367 lines
| 1 | /*! |
| 2 | * ng-i18next - Version 1.0.4 - 2017-05-26 |
| 3 | * Copyright (c) 2017 Andre Meyering |
| 4 | * |
| 5 | * AngularJS provider, filter and directive for i18next (i18next by Jan Mühlemann) |
| 6 | * |
| 7 | * - Source: https://github.com/i18next/ng-i18next/ |
| 8 | * - Issues: https://github.com/i18next/ng-i18next/issues |
| 9 | * |
| 10 | * License: MIT - https://github.com/i18next/ng-i18next/blob/master/LICENSE |
| 11 | * |
| 12 | */ |
| 13 | (function (global, factory) { |
| 14 | typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('angular')) : |
| 15 | typeof define === 'function' && define.amd ? define(['angular'], factory) : |
| 16 | (global.ngI18next = factory(global.angular)); |
| 17 | }(this, (function (angular) { 'use strict'; |
| 18 | |
| 19 | var I18nDirective = (function () { |
| 20 | function I18nDirective($interpolate) { |
| 21 | var _this = this; |
| 22 | this.$interpolate = $interpolate; |
| 23 | this.restrict = 'A'; |
| 24 | this.scope = false; |
| 25 | this.controller = 'NgI18nextController'; |
| 26 | this.link = function ($scope, $element, $attrs, ctrl) { |
| 27 | var self = _this; |
| 28 | var translationValue = ''; |
| 29 | var isTransformed = false; |
| 30 | translationValue = $attrs.ngI18next.replace(/^\s+|\s+$/g, ''); |
| 31 | if (translationValue.indexOf('__once__') < 0) { |
| 32 | $attrs.$observe('ngI18next', observe); |
| 33 | } |
| 34 | else { |
| 35 | // Remove '__once__' |
| 36 | translationValue = translationValue.split('__once__').join(''); |
| 37 | ctrl.localize(translationValue, true); |
| 38 | } |
| 39 | $scope.$on('i18nextLanguageChange', function () { |
| 40 | ctrl.localize(translationValue); |
| 41 | }); |
| 42 | function observe(value) { |
| 43 | if (angular.isDefined(value)) { |
| 44 | translationValue = value.replace(/^\s+|\s+$/g, ''); // RegEx removes whitespace |
| 45 | if (translationValue === '') { |
| 46 | return setupWatcher(); |
| 47 | } |
| 48 | ctrl.localize(translationValue); |
| 49 | } |
| 50 | } |
| 51 | function setupWatcher() { |
| 52 | // Prevent from executing this method twice |
| 53 | if (isTransformed) { |
| 54 | return; |
| 55 | } |
| 56 | // interpolate is allowing to transform {{expr}} into text |
| 57 | var interpolation = self.$interpolate($element.html()); |
| 58 | $scope.$watch(interpolation, observe); |
| 59 | isTransformed = true; |
| 60 | } |
| 61 | }; |
| 62 | } |
| 63 | I18nDirective.factory = function () { |
| 64 | var directive = function ($interpolate) { return new I18nDirective($interpolate); }; |
| 65 | directive.$inject = ['$interpolate']; |
| 66 | return directive; |
| 67 | }; |
| 68 | return I18nDirective; |
| 69 | }()); |
| 70 | |
| 71 | var I18nBindOnceDirective = (function () { |
| 72 | function I18nBindOnceDirective($compile) { |
| 73 | var _this = this; |
| 74 | this.$compile = $compile; |
| 75 | this.restrict = 'A'; |
| 76 | this.scope = false; |
| 77 | this.link = function (scope, element, attrs) { |
| 78 | var newElement = element.clone(); |
| 79 | newElement.attr('ng-i18next', '__once__' + attrs.boI18next); |
| 80 | newElement.removeAttr('bo-i18next'); |
| 81 | element.replaceWith(_this.$compile(newElement)(scope)); |
| 82 | }; |
| 83 | } |
| 84 | I18nBindOnceDirective.factory = function () { |
| 85 | var directive = function ($compile) { return new I18nBindOnceDirective($compile); }; |
| 86 | directive.$inject = ['$compile']; |
| 87 | return directive; |
| 88 | }; |
| 89 | return I18nBindOnceDirective; |
| 90 | }()); |
| 91 | |
| 92 | var I18nDirectiveController = (function () { |
| 93 | function I18nDirectiveController($scope, $element, $compile, $parse, $interpolate, $sanitize, $i18next) { |
| 94 | this.$scope = $scope; |
| 95 | this.$element = $element; |
| 96 | this.$compile = $compile; |
| 97 | this.$parse = $parse; |
| 98 | this.$interpolate = $interpolate; |
| 99 | this.$sanitize = $sanitize; |
| 100 | this.$i18next = $i18next; |
| 101 | } |
| 102 | I18nDirectiveController.prototype.localize = function (key, noWatch) { |
| 103 | var keys = key.split(';'); |
| 104 | for (var i = 0; i < keys.length; ++i) { |
| 105 | key = keys[i].trim(); |
| 106 | if (key === '') { |
| 107 | continue; |
| 108 | } |
| 109 | this.parse(key, noWatch); |
| 110 | } |
| 111 | }; |
| 112 | |
| 113 | I18nDirectiveController.prototype.parse = function (key, noWatch) { |
| 114 | var _this = this; |
| 115 | var parsedKey = this.parseKey(key); |
| 116 | // If there are watched values, unregister them |
| 117 | if (this.argsUnregister) { |
| 118 | this.argsUnregister(); |
| 119 | } |
| 120 | if (this.stringUnregister) { |
| 121 | this.stringUnregister(); |
| 122 | } |
| 123 | if (!noWatch) { |
| 124 | this.argsUnregister = this.$scope.$watch(function () { |
| 125 | return parsedKey.i18nOptions(_this.$scope); |
| 126 | }, function () { return _this.render(parsedKey, noWatch); }, true); |
| 127 | } |
| 128 | this.render(parsedKey, noWatch); |
| 129 | }; |
| 130 | I18nDirectiveController.prototype.parseKey = function (key) { |
| 131 | var options = { |
| 132 | attr: 'text', |
| 133 | }; |
| 134 | var i18nOptions = '{}'; |
| 135 | var tmp; |
| 136 | key = key.trim(); |
| 137 | if (key.indexOf('[') === 0) { |
| 138 | tmp = key.split(']'); |
| 139 | options = this.parseOptions(tmp.shift().substr(1).trim()); |
| 140 | key = tmp.join(']'); |
| 141 | } |
| 142 | if (key.indexOf('(') === 0 && key.indexOf(')') >= 0) { |
| 143 | tmp = key.split(')'); |
| 144 | key = tmp.pop().trim(); |
| 145 | i18nOptions = tmp.join(')').substr(1).trim(); |
| 146 | } |
| 147 | var parsedKey = { |
| 148 | i18nOptions: this.$parse(i18nOptions), |
| 149 | key: key, |
| 150 | options: options, |
| 151 | }; |
| 152 | return parsedKey; |
| 153 | }; |
| 154 | I18nDirectiveController.prototype.parseOptions = function (options) { |
| 155 | var res = { |
| 156 | attr: 'text', |
| 157 | }; |
| 158 | var optionsSplit = options.split(':'); |
| 159 | for (var i = 0; i < optionsSplit.length; ++i) { |
| 160 | if (optionsSplit[i] === 'i18next') { |
| 161 | res[optionsSplit[i]] = true; |
| 162 | } |
| 163 | else { |
| 164 | res.attr = optionsSplit[i]; |
| 165 | } |
| 166 | } |
| 167 | return res; |
| 168 | }; |
| 169 | I18nDirectiveController.prototype.render = function (parsedKey, noWatch) { |
| 170 | if (angular.isDefined(this) && angular.isDefined(this.$scope)) { |
| 171 | var i18nOptions_1 = parsedKey.i18nOptions(this.$scope); |
| 172 | if (i18nOptions_1.sprintf) { |
| 173 | i18nOptions_1.postProcess = 'sprintf'; |
| 174 | } |
| 175 | if (parsedKey.options.attr === 'html') { |
| 176 | angular.forEach(i18nOptions_1, function (value, key) { |
| 177 | var newValue = undefined; |
| 178 | var sanitized = this.$sanitize(value); |
| 179 | var numeric = Number(value); |
| 180 | if (typeof numeric === 'number' && !isNaN(numeric)) { |
| 181 | newValue = numeric; |
| 182 | } |
| 183 | else { |
| 184 | newValue = sanitized; |
| 185 | } |
| 186 | i18nOptions_1[key] = newValue; // jshint ignore:line |
| 187 | }, this); |
| 188 | } |
| 189 | var localizedString = this.$i18next.t(parsedKey.key, i18nOptions_1); |
| 190 | if (angular.isDefined(localizedString)) { |
| 191 | if (parsedKey.options.attr === 'html') { |
| 192 | this.$element.empty().append(localizedString); |
| 193 | /* |
| 194 | * Now compile the content of the element and bind the variables to |
| 195 | * the scope |
| 196 | */ |
| 197 | this.$compile(this.$element.contents())(this.$scope); |
| 198 | return; |
| 199 | } |
| 200 | if (this.stringUnregister) { |
| 201 | this.stringUnregister(); |
| 202 | } |
| 203 | var insertText = this.$element.text.bind(this.$element); |
| 204 | if (parsedKey.options.attr !== 'text') { |
| 205 | insertText = this.$element.attr.bind(this.$element, parsedKey.options.attr); |
| 206 | } |
| 207 | var localizedStringInterpolation = this.$interpolate(localizedString); |
| 208 | if (!noWatch) { |
| 209 | this.stringUnregister = this.$scope.$watch(localizedStringInterpolation, insertText); |
| 210 | } |
| 211 | insertText(localizedStringInterpolation(this.$scope)); |
| 212 | } |
| 213 | } |
| 214 | }; |
| 215 | I18nDirectiveController.$inject = ['$scope', '$element', '$compile', '$parse', '$interpolate', '$sanitize', '$i18next']; |
| 216 | return I18nDirectiveController; |
| 217 | }()); |
| 218 | |
| 219 | var I18nFilter = (function () { |
| 220 | function I18nFilter() { |
| 221 | } |
| 222 | I18nFilter.factory = function () { |
| 223 | var filter = function ($i18next) { |
| 224 | function i18nextFilter(key, options) { |
| 225 | var localOptions = angular.isDefined(options) ? options : {}; |
| 226 | return $i18next.t(key, localOptions); |
| 227 | } |
| 228 | i18nextFilter.$stateful = true; |
| 229 | return i18nextFilter; |
| 230 | }; |
| 231 | filter.$inject = ['$i18next']; |
| 232 | return filter; |
| 233 | }; |
| 234 | return I18nFilter; |
| 235 | }()); |
| 236 | |
| 237 | var I18nTranslateService = (function () { |
| 238 | function I18nTranslateService($rootScope, translationOptions) { |
| 239 | this.$rootScope = $rootScope; |
| 240 | this.options = {}; |
| 241 | this.tOptions = {}; |
| 242 | this.modules = []; |
| 243 | this.translations = {}; |
| 244 | this.i18n = i18next; |
| 245 | this.tOptions = translationOptions; |
| 246 | this.initializeI18next(); |
| 247 | } |
| 248 | I18nTranslateService.prototype.t = function (key, ownOptions) { |
| 249 | var hasOwnOptions = angular.isDefined(ownOptions); |
| 250 | var hasOwnNsOption = hasOwnOptions && angular.isDefined(ownOptions.ns); |
| 251 | var hasInitNsObj = angular.isDefined(this.options) && angular.isDefined(this.options.ns); |
| 252 | var defaultOptions = this.options; |
| 253 | var mergedOptions; |
| 254 | var lng; |
| 255 | // https://github.com/i18next/i18next/blob/e47bdb4d5528c752499b0209d829fde4e1cc96e7/src/i18next.translate.js#L232 |
| 256 | // Because of i18next read namespace from `options.ns` |
| 257 | if (angular.isUndefined(hasOwnNsOption) && hasInitNsObj) { |
| 258 | defaultOptions = angular.extend({}, this.options); |
| 259 | defaultOptions.ns = defaultOptions.defaultNS; |
| 260 | } |
| 261 | mergedOptions = hasOwnOptions ? ownOptions : this.tOptions; |
| 262 | // https://github.com/i18next/i18next/blob/7af53d5a01cc9942c0edae361bd2f65361e340c9/src/i18next.translate.js#L289 |
| 263 | // lng will be deleted in some case |
| 264 | lng = mergedOptions.lng; |
| 265 | this.translate(key, mergedOptions, hasOwnOptions); |
| 266 | return angular.isDefined(lng) ? this.translations[lng][key] : this.translations['auto'][key]; |
| 267 | }; |
| 268 | //JetApps |
| 269 | I18nTranslateService.prototype.setDefaultNamespace = function (ns) { |
| 270 | var _this = this; |
| 271 | this.translations = {}; |
| 272 | if (this.options.defaultNS !== ns) { |
| 273 | this.options.defaultNS = ns; |
| 274 | this.i18n.setDefaultNamespace(ns, function (err, t) { |
| 275 | _this.$rootScope.$broadcast('i18nextDefaultNSChange', _this.i18n.defaultNS); |
| 276 | }); |
| 277 | } |
| 278 | }; |
| 279 | //JetApps |
| 280 | I18nTranslateService.prototype.loadNamespaces = function (ns) { |
| 281 | var _this = this; |
| 282 | this.translations = {}; |
| 283 | this.i18n.loadNamespaces(ns, function (err, t) { |
| 284 | _this.$rootScope.$broadcast('i18nextNSLoad', _this.i18n.ns); |
| 285 | }); |
| 286 | |
| 287 | }; |
| 288 | I18nTranslateService.prototype.changeLanguage = function (lng) { |
| 289 | var _this = this; |
| 290 | this.translations = {}; |
| 291 | if (this.options.lng !== lng && this.i18n.language !== lng) { |
| 292 | this.options.lng = lng; |
| 293 | this.i18n.changeLanguage(lng, function (err, t) { |
| 294 | _this.$rootScope.$broadcast('i18nextLanguageChange', _this.i18n.language); |
| 295 | }); |
| 296 | } |
| 297 | }; |
| 298 | I18nTranslateService.prototype.changeOptions = function (options) { |
| 299 | if (angular.isDefined(options)) { |
| 300 | this.options = options; |
| 301 | } |
| 302 | }; |
| 303 | I18nTranslateService.prototype.initializeI18next = function () { |
| 304 | var self = this; |
| 305 | if (i18next) { |
| 306 | // assign instance of i18next |
| 307 | this.i18n = i18next; |
| 308 | this.options = i18next.options; |
| 309 | } |
| 310 | else { |
| 311 | var error = new Error('[ng-i18next] Can\'t find i18next and/or i18next options! Please refer to i18next.'); |
| 312 | this.handleError(error); |
| 313 | } |
| 314 | i18next.on('initialized', function (options) { |
| 315 | self.options = options; |
| 316 | self.$rootScope.$broadcast('i18nextLanguageChange', self.options.lng); |
| 317 | }); |
| 318 | }; |
| 319 | I18nTranslateService.prototype.translate = function (key, tOptions, hasOwnOptions) { |
| 320 | var localOptions = angular.isDefined(tOptions) && hasOwnOptions ? tOptions : this.tOptions; |
| 321 | var lng = localOptions.lng || 'auto'; |
| 322 | if (angular.isUndefined(this.translations[lng])) { |
| 323 | this.translations[lng] = {}; |
| 324 | } |
| 325 | if (angular.isUndefined(this.i18n)) { |
| 326 | this.translations[lng][key] = angular.isDefined(localOptions.defaultValue) ? localOptions.defaultValue : key; |
| 327 | } |
| 328 | else if (angular.isUndefined(this.translations[lng][key]) || hasOwnOptions) { |
| 329 | this.translations[lng][key] = this.i18n.t(key, localOptions); |
| 330 | } |
| 331 | }; |
| 332 | I18nTranslateService.prototype.handleError = function (error) { |
| 333 | var message = angular.isDefined(error.message) ? error.message : error[0]; |
| 334 | // tslint:disable-next-line:no-console |
| 335 | console.log(message); |
| 336 | }; |
| 337 | return I18nTranslateService; |
| 338 | }()); |
| 339 | |
| 340 | var I18nProvider = (function () { |
| 341 | function I18nProvider() { |
| 342 | var _this = this; |
| 343 | this.translationOptions = {}; |
| 344 | this.$get = function ($rootScope) { |
| 345 | if (i18next) { |
| 346 | return new I18nTranslateService($rootScope, _this.translationOptions); |
| 347 | } |
| 348 | else { |
| 349 | throw 'i18next is not loaded'; |
| 350 | } |
| 351 | }; |
| 352 | this.$get.$inject = ['$rootScope']; |
| 353 | } |
| 354 | return I18nProvider; |
| 355 | }()); |
| 356 | angular.module('jm.i18next', ['ng', 'ngSanitize']) |
| 357 | .provider('$i18next', I18nProvider) |
| 358 | .directive('ngI18next', I18nDirective.factory()) |
| 359 | .directive('boI18next', I18nBindOnceDirective.factory()) |
| 360 | .controller('NgI18nextController', I18nDirectiveController) |
| 361 | .filter('i18next', I18nFilter.factory()); |
| 362 | var provider = 'jm.i18next'; |
| 363 | |
| 364 | return provider; |
| 365 | |
| 366 | }))); |
| 367 |