Răsfoiți Sursa

I18n support, fixed version in footer

Jamie Curnow 7 ani în urmă
părinte
comite
d49c3ba3af

+ 3 - 1
src/frontend/js/app/cache.js

@@ -3,7 +3,9 @@
 const UserModel = require('../models/user');
 
 let cache = {
-    User: new UserModel.Model()
+    User:    new UserModel.Model(),
+    locale:  'en',
+    version: null
 };
 
 module.exports = cache;

+ 25 - 0
src/frontend/js/app/i18n.js

@@ -0,0 +1,25 @@
+'use strict';
+
+const Cache    = ('./cache');
+const messages = require('../i18n/messages.json');
+
+/**
+ * @param {String}  namespace
+ * @param {String}  key
+ * @param {Object}  [data]
+ */
+module.exports = function (namespace, key, data) {
+    let locale = Cache.locale;
+    // check that the locale exists
+    if (typeof messages[locale] === 'undefined') {
+        locale = 'en';
+    }
+
+    if (typeof messages[locale][namespace] !== 'undefined' && typeof messages[locale][namespace][key] !== 'undefined') {
+        return messages[locale][namespace][key](data);
+    } else if (locale !== 'en' && typeof messages['en'][namespace] !== 'undefined' && typeof messages['en'][namespace][key] !== 'undefined') {
+        return messages['en'][namespace][key](data);
+    }
+
+    return 'INVALID I18N: ' + namespace + '/' + key;
+};

+ 6 - 7
src/frontend/js/app/main.js

@@ -9,6 +9,7 @@ const Router     = require('./router');
 const Api        = require('./api');
 const Tokens     = require('./tokens');
 const UI         = require('./ui/main');
+const i18n       = require('./i18n');
 
 const App = Mn.Application.extend({
 
@@ -16,7 +17,6 @@ const App = Mn.Application.extend({
     Api:        Api,
     UI:         null,
     Controller: Controller,
-    version:    null,
 
     region: {
         el:             '#app',
@@ -24,7 +24,7 @@ const App = Mn.Application.extend({
     },
 
     onStart: function (app, options) {
-        console.log('Welcome to Nginx Proxy Manager');
+        console.log(i18n('main', 'welcome'));
 
         // Check if token is coming through
         if (this.getParam('token')) {
@@ -34,12 +34,12 @@ const App = Mn.Application.extend({
         // Check if we are still logged in by refreshing the token
         Api.status()
             .then(result => {
-                this.version = [result.version.major, result.version.minor, result.version.revision].join('.');
+                Cache.version = [result.version.major, result.version.minor, result.version.revision].join('.');
             })
             .then(Api.Tokens.refresh)
             .then(this.bootstrap)
             .then(() => {
-                console.info('You are logged in');
+                console.info(i18n('main', 'logged-in', Cache.User.attributes));
                 this.bootstrapTimer();
                 this.refreshTokenTimer();
 
@@ -60,7 +60,6 @@ const App = Mn.Application.extend({
                 console.warn('Not logged in:', err.message);
                 Controller.showLogin();
             });
-
     },
 
     History: {
@@ -86,7 +85,7 @@ const App = Mn.Application.extend({
         let ErrorView = Mn.View.extend({
             tagName:  'section',
             id:       'error',
-            template: _.template('Error loading stuff. Please reload the app.')
+            template: _.template(i18n('main', 'unknown-error'))
         });
 
         this.getRegion().show(new ErrorView());
@@ -130,7 +129,7 @@ const App = Mn.Application.extend({
             Api.status()
                 .then(result => {
                     let version = [result.version.major, result.version.minor, result.version.revision].join('.');
-                    if (version !== this.version) {
+                    if (version !== Cache.version) {
                         document.location.reload();
                     }
                 })

+ 4 - 2
src/frontend/js/app/ui/footer/main.ejs

@@ -3,12 +3,14 @@
         <div class="row align-items-center">
             <div class="col-auto">
                 <ul class="list-inline list-inline-dots mb-0">
-                    <li class="list-inline-item"><a href="https://github.com/jc21/docker-registry-ui?utm_source=docker-registry-ui">Fork me on Github</a></li>
+                    <li class="list-inline-item"><a href="https://github.com/jc21/nginx-proxy-manager?utm_source=nginx-proxy-manager"><%- i18n('footer', 'fork-me') %></a></li>
                 </ul>
             </div>
         </div>
     </div>
     <div class="col-12 col-lg-auto mt-3 mt-lg-0 text-center">
-        v<%- getVersion() %> &copy; 2018 <a href="https://jc21.com?utm_source=nginx-proxy-manager" target="_blank">jc21.com</a>. Theme by <a href="https://tabler.github.io/?utm_source=nginx-proxy-manager" target="_blank">Tabler</a>
+        <%- i18n('footer', 'version', {version: getVersion()}) %>
+        <%= i18n('footer', 'copy', {url: 'https://jc21.com?utm_source=nginx-proxy-manager'}) %>
+        <%= i18n('footer', 'theme', {url: 'https://tabler.github.io/?utm_source=nginx-proxy-manager'}) %>
     </div>
 </div>

+ 2 - 2
src/frontend/js/app/ui/footer/main.js

@@ -2,7 +2,7 @@
 
 const Mn       = require('backbone.marionette');
 const template = require('./main.ejs');
-const App      = require('../../main');
+const Cache    = require('../../cache');
 
 module.exports = Mn.View.extend({
     className: 'container',
@@ -10,7 +10,7 @@ module.exports = Mn.View.extend({
 
     templateContext: {
         getVersion: function () {
-            return App.version;
+            return Cache.version || '0.0.0';
         }
     }
 });

+ 4 - 4
src/frontend/js/app/ui/header/main.ejs

@@ -1,7 +1,7 @@
 <div class="container">
     <div class="d-flex">
         <a class="navbar-brand" href="/">
-            <img src="/images/favicons/favicon-32x32.png" border="0"> &nbsp; Nginx Proxy Manager
+            <img src="/images/favicons/favicon-32x32.png" border="0"> &nbsp; <%- i18n('main', 'app') %>
         </a>
 
         <div class="d-flex order-lg-2 ml-auto">
@@ -9,16 +9,16 @@
                 <a href="#" class="nav-link pr-0 leading-none" data-toggle="dropdown">
                     <span class="avatar" style="background-image: url(<%- getUserField('avatar', '/images/default-avatar.jpg') %>)"></span>
                     <span class="ml-2 d-none d-lg-block">
-                      <span class="text-default"><%- getUserField('nickname', null) || getUserField('name', 'Unknown User') %></span>
+                      <span class="text-default"><%- getUserField('nickname', null) || getUserField('name', i18n('main', 'unknown-user')) %></span>
                       <small class="text-muted d-block mt-1"><%- getRole() %></small>
                     </span>
                 </a>
                 <div class="dropdown-menu dropdown-menu-right dropdown-menu-arrow">
                     <a class="dropdown-item edit-details" href="#">
-                        <i class="dropdown-icon fe fe-user"></i> Edit Details
+                        <i class="dropdown-icon fe fe-user"></i> <%- i18n('user', 'edit-details') %>
                     </a>
                     <a class="dropdown-item change-password" href="#">
-                        <i class="dropdown-icon fe fe-lock"></i> Change Password
+                        <i class="dropdown-icon fe fe-lock"></i> <%- i18n('user', 'change-password') %>
                     </a>
                     <div class="dropdown-divider"></div>
                     <a class="dropdown-item logout" href="/logout">

+ 4 - 3
src/frontend/js/app/ui/header/main.js

@@ -2,6 +2,7 @@
 
 const $          = require('jquery');
 const Mn         = require('backbone.marionette');
+const i18n       = require('../../i18n');
 const Cache      = require('../../cache');
 const Controller = require('../../controller');
 const Tokens     = require('../../tokens');
@@ -50,15 +51,15 @@ module.exports = Mn.View.extend({
         },
 
         getRole: function () {
-            return Cache.User.isAdmin() ? 'Administrator' : 'Apache Helicopter';
+            return i18n('roles', Cache.User.isAdmin() ? 'admin' : 'user');
         },
 
         getLogoutText: function () {
             if (Tokens.getTokenCount() > 1) {
-                return 'Sign back in as ' + Tokens.getNextTokenName();
+                return i18n('main', 'sign-in-as', {name: Tokens.getNextTokenName()});
             }
 
-            return 'Sign out';
+            return i18n('main', 'sign-out');
         }
     },
 

+ 27 - 0
src/frontend/js/i18n/messages.json

@@ -0,0 +1,27 @@
+{
+  "en": {
+    "main": {
+      "app": "Nginx Proxy Manager",
+      "welcome": "Welcome to Nginx Proxy Manager",
+      "logged-in": "You are logged in as {name}",
+      "unknown-error": "Error loading stuff. Please reload the app.",
+      "unknown-user": "Unknown User",
+      "sign-out": "Sign out",
+      "sign-in-as": "Sign back in as {name}"
+    },
+    "user": {
+      "edit-details": "Edit Details",
+      "change-password": "Change Password"
+    },
+    "roles": {
+      "admin": "Administrator",
+      "user": "Apache Helicopter"
+    },
+    "footer": {
+      "fork-me": "Fork me on Github",
+      "copy": "&copy; 2018 <a href=\"{url}\" target=\"_blank\">jc21.com</a>.",
+      "version": "v{version}",
+      "theme": "Theme by <a href=\"{url}\" target=\"_blank\">Tabler</a>"
+    }
+  }
+}

+ 3 - 0
src/frontend/js/lib/marionette.js

@@ -4,6 +4,7 @@ const _       = require('underscore');
 const Mn      = require('backbone.marionette');
 const moment  = require('moment');
 const numeral = require('numeral');
+const i18n    = require('../app/i18n');
 
 let render = Mn.Renderer.render;
 
@@ -11,6 +12,8 @@ Mn.Renderer.render = function (template, data, view) {
 
     data = _.clone(data);
 
+    data.i18n = i18n;
+
     /**
      * @param   {Integer} number
      * @returns {String}

+ 13 - 0
webpack.config.js

@@ -45,6 +45,19 @@ module.exports = {
             },
 
             // other:
+            {
+                type:    'javascript/auto', // <= Set the module.type explicitly
+                test:    /\bmessages\.json$/,
+                loader:  'messageformat-loader',
+                options: {
+                    biDiSupport:            false,
+                    disablePluralKeyChecks: false,
+                    formatters:             null,
+                    intlSupport:            false,
+                    locale:                 ['en'/*, 'es'*/],
+                    strictNumberSign:       false
+                }
+            },
             {
                 test:    /\.js$/,
                 exclude: /node_modules/,