mirror of
				https://github.com/NginxProxyManager/nginx-proxy-manager.git
				synced 2025-10-31 15:53:33 +00:00 
			
		
		
		
	I18n support, fixed version in footer
This commit is contained in:
		| @@ -3,7 +3,9 @@ | |||||||
| const UserModel = require('../models/user'); | const UserModel = require('../models/user'); | ||||||
|  |  | ||||||
| let cache = { | let cache = { | ||||||
|     User: new UserModel.Model() |     User:    new UserModel.Model(), | ||||||
|  |     locale:  'en', | ||||||
|  |     version: null | ||||||
| }; | }; | ||||||
|  |  | ||||||
| module.exports = cache; | module.exports = cache; | ||||||
|   | |||||||
							
								
								
									
										25
									
								
								src/frontend/js/app/i18n.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								src/frontend/js/app/i18n.js
									
									
									
									
									
										Normal file
									
								
							| @@ -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; | ||||||
|  | }; | ||||||
| @@ -9,6 +9,7 @@ const Router     = require('./router'); | |||||||
| const Api        = require('./api'); | const Api        = require('./api'); | ||||||
| const Tokens     = require('./tokens'); | const Tokens     = require('./tokens'); | ||||||
| const UI         = require('./ui/main'); | const UI         = require('./ui/main'); | ||||||
|  | const i18n       = require('./i18n'); | ||||||
|  |  | ||||||
| const App = Mn.Application.extend({ | const App = Mn.Application.extend({ | ||||||
|  |  | ||||||
| @@ -16,7 +17,6 @@ const App = Mn.Application.extend({ | |||||||
|     Api:        Api, |     Api:        Api, | ||||||
|     UI:         null, |     UI:         null, | ||||||
|     Controller: Controller, |     Controller: Controller, | ||||||
|     version:    null, |  | ||||||
|  |  | ||||||
|     region: { |     region: { | ||||||
|         el:             '#app', |         el:             '#app', | ||||||
| @@ -24,7 +24,7 @@ const App = Mn.Application.extend({ | |||||||
|     }, |     }, | ||||||
|  |  | ||||||
|     onStart: function (app, options) { |     onStart: function (app, options) { | ||||||
|         console.log('Welcome to Nginx Proxy Manager'); |         console.log(i18n('main', 'welcome')); | ||||||
|  |  | ||||||
|         // Check if token is coming through |         // Check if token is coming through | ||||||
|         if (this.getParam('token')) { |         if (this.getParam('token')) { | ||||||
| @@ -34,12 +34,12 @@ const App = Mn.Application.extend({ | |||||||
|         // Check if we are still logged in by refreshing the token |         // Check if we are still logged in by refreshing the token | ||||||
|         Api.status() |         Api.status() | ||||||
|             .then(result => { |             .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(Api.Tokens.refresh) | ||||||
|             .then(this.bootstrap) |             .then(this.bootstrap) | ||||||
|             .then(() => { |             .then(() => { | ||||||
|                 console.info('You are logged in'); |                 console.info(i18n('main', 'logged-in', Cache.User.attributes)); | ||||||
|                 this.bootstrapTimer(); |                 this.bootstrapTimer(); | ||||||
|                 this.refreshTokenTimer(); |                 this.refreshTokenTimer(); | ||||||
|  |  | ||||||
| @@ -60,7 +60,6 @@ const App = Mn.Application.extend({ | |||||||
|                 console.warn('Not logged in:', err.message); |                 console.warn('Not logged in:', err.message); | ||||||
|                 Controller.showLogin(); |                 Controller.showLogin(); | ||||||
|             }); |             }); | ||||||
|  |  | ||||||
|     }, |     }, | ||||||
|  |  | ||||||
|     History: { |     History: { | ||||||
| @@ -86,7 +85,7 @@ const App = Mn.Application.extend({ | |||||||
|         let ErrorView = Mn.View.extend({ |         let ErrorView = Mn.View.extend({ | ||||||
|             tagName:  'section', |             tagName:  'section', | ||||||
|             id:       'error', |             id:       'error', | ||||||
|             template: _.template('Error loading stuff. Please reload the app.') |             template: _.template(i18n('main', 'unknown-error')) | ||||||
|         }); |         }); | ||||||
|  |  | ||||||
|         this.getRegion().show(new ErrorView()); |         this.getRegion().show(new ErrorView()); | ||||||
| @@ -130,7 +129,7 @@ const App = Mn.Application.extend({ | |||||||
|             Api.status() |             Api.status() | ||||||
|                 .then(result => { |                 .then(result => { | ||||||
|                     let version = [result.version.major, result.version.minor, result.version.revision].join('.'); |                     let version = [result.version.major, result.version.minor, result.version.revision].join('.'); | ||||||
|                     if (version !== this.version) { |                     if (version !== Cache.version) { | ||||||
|                         document.location.reload(); |                         document.location.reload(); | ||||||
|                     } |                     } | ||||||
|                 }) |                 }) | ||||||
|   | |||||||
| @@ -3,12 +3,14 @@ | |||||||
|         <div class="row align-items-center"> |         <div class="row align-items-center"> | ||||||
|             <div class="col-auto"> |             <div class="col-auto"> | ||||||
|                 <ul class="list-inline list-inline-dots mb-0"> |                 <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> |                 </ul> | ||||||
|             </div> |             </div> | ||||||
|         </div> |         </div> | ||||||
|     </div> |     </div> | ||||||
|     <div class="col-12 col-lg-auto mt-3 mt-lg-0 text-center"> |     <div class="col-12 col-lg-auto mt-3 mt-lg-0 text-center"> | ||||||
|         v<%- getVersion() %> © 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> | ||||||
| </div> | </div> | ||||||
|   | |||||||
| @@ -2,7 +2,7 @@ | |||||||
|  |  | ||||||
| const Mn       = require('backbone.marionette'); | const Mn       = require('backbone.marionette'); | ||||||
| const template = require('./main.ejs'); | const template = require('./main.ejs'); | ||||||
| const App      = require('../../main'); | const Cache    = require('../../cache'); | ||||||
|  |  | ||||||
| module.exports = Mn.View.extend({ | module.exports = Mn.View.extend({ | ||||||
|     className: 'container', |     className: 'container', | ||||||
| @@ -10,7 +10,7 @@ module.exports = Mn.View.extend({ | |||||||
|  |  | ||||||
|     templateContext: { |     templateContext: { | ||||||
|         getVersion: function () { |         getVersion: function () { | ||||||
|             return App.version; |             return Cache.version || '0.0.0'; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| }); | }); | ||||||
|   | |||||||
| @@ -1,7 +1,7 @@ | |||||||
| <div class="container"> | <div class="container"> | ||||||
|     <div class="d-flex"> |     <div class="d-flex"> | ||||||
|         <a class="navbar-brand" href="/"> |         <a class="navbar-brand" href="/"> | ||||||
|             <img src="/images/favicons/favicon-32x32.png" border="0">   Nginx Proxy Manager |             <img src="/images/favicons/favicon-32x32.png" border="0">   <%- i18n('main', 'app') %> | ||||||
|         </a> |         </a> | ||||||
|  |  | ||||||
|         <div class="d-flex order-lg-2 ml-auto"> |         <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"> |                 <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="avatar" style="background-image: url(<%- getUserField('avatar', '/images/default-avatar.jpg') %>)"></span> | ||||||
|                     <span class="ml-2 d-none d-lg-block"> |                     <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> |                       <small class="text-muted d-block mt-1"><%- getRole() %></small> | ||||||
|                     </span> |                     </span> | ||||||
|                 </a> |                 </a> | ||||||
|                 <div class="dropdown-menu dropdown-menu-right dropdown-menu-arrow"> |                 <div class="dropdown-menu dropdown-menu-right dropdown-menu-arrow"> | ||||||
|                     <a class="dropdown-item edit-details" href="#"> |                     <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> | ||||||
|                     <a class="dropdown-item change-password" href="#"> |                     <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> |                     </a> | ||||||
|                     <div class="dropdown-divider"></div> |                     <div class="dropdown-divider"></div> | ||||||
|                     <a class="dropdown-item logout" href="/logout"> |                     <a class="dropdown-item logout" href="/logout"> | ||||||
|   | |||||||
| @@ -2,6 +2,7 @@ | |||||||
|  |  | ||||||
| const $          = require('jquery'); | const $          = require('jquery'); | ||||||
| const Mn         = require('backbone.marionette'); | const Mn         = require('backbone.marionette'); | ||||||
|  | const i18n       = require('../../i18n'); | ||||||
| const Cache      = require('../../cache'); | const Cache      = require('../../cache'); | ||||||
| const Controller = require('../../controller'); | const Controller = require('../../controller'); | ||||||
| const Tokens     = require('../../tokens'); | const Tokens     = require('../../tokens'); | ||||||
| @@ -50,15 +51,15 @@ module.exports = Mn.View.extend({ | |||||||
|         }, |         }, | ||||||
|  |  | ||||||
|         getRole: function () { |         getRole: function () { | ||||||
|             return Cache.User.isAdmin() ? 'Administrator' : 'Apache Helicopter'; |             return i18n('roles', Cache.User.isAdmin() ? 'admin' : 'user'); | ||||||
|         }, |         }, | ||||||
|  |  | ||||||
|         getLogoutText: function () { |         getLogoutText: function () { | ||||||
|             if (Tokens.getTokenCount() > 1) { |             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
									
								
								src/frontend/js/i18n/messages.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								src/frontend/js/i18n/messages.json
									
									
									
									
									
										Normal file
									
								
							| @@ -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": "© 2018 <a href=\"{url}\" target=\"_blank\">jc21.com</a>.", | ||||||
|  |       "version": "v{version}", | ||||||
|  |       "theme": "Theme by <a href=\"{url}\" target=\"_blank\">Tabler</a>" | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
| @@ -4,6 +4,7 @@ const _       = require('underscore'); | |||||||
| const Mn      = require('backbone.marionette'); | const Mn      = require('backbone.marionette'); | ||||||
| const moment  = require('moment'); | const moment  = require('moment'); | ||||||
| const numeral = require('numeral'); | const numeral = require('numeral'); | ||||||
|  | const i18n    = require('../app/i18n'); | ||||||
|  |  | ||||||
| let render = Mn.Renderer.render; | let render = Mn.Renderer.render; | ||||||
|  |  | ||||||
| @@ -11,6 +12,8 @@ Mn.Renderer.render = function (template, data, view) { | |||||||
|  |  | ||||||
|     data = _.clone(data); |     data = _.clone(data); | ||||||
|  |  | ||||||
|  |     data.i18n = i18n; | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * @param   {Integer} number |      * @param   {Integer} number | ||||||
|      * @returns {String} |      * @returns {String} | ||||||
|   | |||||||
| @@ -45,6 +45,19 @@ module.exports = { | |||||||
|             }, |             }, | ||||||
|  |  | ||||||
|             // other: |             // 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$/, |                 test:    /\.js$/, | ||||||
|                 exclude: /node_modules/, |                 exclude: /node_modules/, | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user