diff --git a/src/generators/app/index.js b/src/generators/app/index.js index b110938dd..6d03516ab 100644 --- a/src/generators/app/index.js +++ b/src/generators/app/index.js @@ -189,6 +189,11 @@ export class Generator extends Base { filter: val => val.toLowerCase() }, { type: 'confirm', + name: 'i18nSupport', + default: false, + message: 'Would you like to include i18n support (multi-language)?' + }, { + type: 'confirm', name: 'bootstrap', message: 'Would you like to include Bootstrap?' }, { @@ -219,6 +224,9 @@ export class Generator extends Base { this.filters.uibootstrap = !!answers.uibootstrap; insight.track('uibootstrap', !!answers.uibootstrap); + this.filters.i18nSupport = !!answers.i18nSupport; + insight.track('i18nSupport', !!answers.i18nSupport); + this.scriptExt = answers.transpiler === 'ts' ? 'ts' : 'js'; this.templateExt = answers.markup; @@ -444,6 +452,7 @@ export class Generator extends Base { if(this.filters.socketio) angModules.push("'btford.socket-io'"); if(this.filters.uirouter) angModules.push("'ui.router'"); if(this.filters.uibootstrap) angModules.push("'ui.bootstrap'"); + if(this.filters.auth) { angModules.unshift(`'${this.scriptAppName}.admin'`); angModules.unshift(`'${this.scriptAppName}.auth'`); @@ -548,6 +557,10 @@ export class Generator extends Base { ['uiBootstrap', 'angular-ui-bootstrap'], ['ngMessages', 'angular-messages'], ['io', 'socket.io-client'], + ['i18n', 'angular-translate'], + ['i18nCookie', 'angular-translate-storage-cookie'], + ['i18nLocal', 'angular-translate-storage-local'], + ['i18nLoader', 'angular-translate-loader-static-files'], ['ngValidationMatch', 'angular-validation-match'] ]; function replacer(contents) { diff --git a/src/test/fixtures/.yo-rc.json b/src/test/fixtures/.yo-rc.json index ca971c119..1cfff6c65 100644 --- a/src/test/fixtures/.yo-rc.json +++ b/src/test/fixtures/.yo-rc.json @@ -21,6 +21,7 @@ "uirouter": true, "bootstrap": true, "uibootstrap": true, + "i18nSupport": false, "socketio": true, "auth": true, "models": true, diff --git a/src/test/get-expected-files.js b/src/test/get-expected-files.js index 73e5e00f7..15d0d6b54 100644 --- a/src/test/get-expected-files.js +++ b/src/test/get-expected-files.js @@ -136,6 +136,16 @@ export function app(options) { 'client/components/ui-router/ui-router.mock.' + script ]); } + + /* i18n Support */ + if (options.i18nSupport) { + files = files.concat([ + 'client/components/i18n/flags.png', + 'client/components/i18n/flags.' + stylesheet, + 'client/components/i18n/locale-en.json', + 'client/components/i18n/locale-fr.json' + ]); + } /* Ui-Bootstrap */ if (options.uibootstrap) { diff --git a/src/test/main.test.js b/src/test/main.test.js index d1010caf5..20c4cd056 100644 --- a/src/test/main.test.js +++ b/src/test/main.test.js @@ -27,7 +27,8 @@ const defaultOptions = { odms: ['mongoose'], auth: true, oauth: [], - socketio: true + socketio: true, + i18nSupport:false }; const TEST_DIR = __dirname; @@ -200,7 +201,8 @@ describe('angular-fullstack:app', function() { oauth: ['twitterAuth', 'facebookAuth', 'googleAuth'], socketio: true, bootstrap: true, - uibootstrap: true + uibootstrap: true, + i18nSupport:false }; before(function() { @@ -272,7 +274,8 @@ describe('angular-fullstack:app', function() { oauth: ['twitterAuth', 'facebookAuth', 'googleAuth'], socketio: true, bootstrap: true, - uibootstrap: true + uibootstrap: true, + i18nSupport:false }; this.retries(3); // Sequelize seems to be quite flaky @@ -343,6 +346,7 @@ describe('angular-fullstack:app', function() { odms: [], auth: false, oauth: [], + i18nSupport:false, socketio: false, bootstrap: false, uibootstrap: false diff --git a/templates/app/_package.json b/templates/app/_package.json index f103b8f5b..80722a812 100644 --- a/templates/app/_package.json +++ b/templates/app/_package.json @@ -19,6 +19,11 @@ "angular-socket-io": "~0.7.0",<% } if(filters.uirouter) { %> "angular-ui-router": "~0.3.1",<% } if(filters.auth) { %> "angular-validation-match": "^1.9.0",<% } %> + <% if (filters.i18nSupport) { %> + "angular-translate": "^2.13.1", + "angular-translate-loader-static-files": "^2.13.1", + "angular-translate-storage-cookie": "^2.13.1", + "angular-translate-storage-local": "^2.13.1", <% } %> <%# END CLIENT %> "core-js": "^2.2.1", "express": "^4.13.3", diff --git a/templates/app/client/app/account(auth)/login/login(html).html b/templates/app/client/app/account(auth)/login/login(html).html index 2f72c7268..c33d8ce6b 100644 --- a/templates/app/client/app/account(auth)/login/login(html).html +++ b/templates/app/client/app/account(auth)/login/login(html).html @@ -1,42 +1,42 @@
-

Login

-

Accounts are reset on server restart from server/config/seed.js. Default account is test@example.com / test

-

Admin account is admin@example.com / admin

+ translate="LOGIN"<% } %>><% if (!filters.i18nSupport) { %>Login<% } %> +

<% if (filters.i18nSupport) { %>{{'ACCOUNT_RESET_MSG' | translate}}<% } else { %>Accounts are reset on server restart from<% } %> server/config/seed.js. <% if (filters.i18nSupport) { %>{{'DEFAUL_ACCOUNT_MSG' | translate}}<% } else { %>Default account is<% } %> test@example.com / test

+

<% if (filters.i18nSupport) { %>{{'ADMIN_ACCOUNT_IS_MSG' | translate}}<% } else { %>Admin account is<% } %> admin@example.com / admin

- + translate="EMAIL"<% } %>><% if (!filters.i18nSupport) { %>Email<% } %>
- + translate="PASSWORD"<% } %>><% if (!filters.i18nSupport) { %>Password<% } %>
-

- Please enter your email and password. +

translate="ENTER_EMAIL_PASSWORD_MSG"<% } %>> + <% if (!filters.i18nSupport) { %>Please enter your email and password.<% } %>

-

- Please enter a valid email. +

translate="ENTER_VALID_EMAIL_MSG"<% } %>> + <% if (!filters.i18nSupport) { %>Please enter a valid email.<% } %>

-

{{ vm.errors.login }}

+

{{ vm.errors.login <% if (filters.i18nSupport) { %> | translate<% } %>}}

- - ui-sref="signup"<% } else { %>href="/signup"<% } %>> - Register + ui-sref="signup"<% } else { %>href="/signup"<% } %><% if (filters.i18nSupport) { %> translate="REGISTER"<% } %>> + <% if (!filters.i18nSupport) { %>Register<% } %>
<% if (filters.oauth) { %> diff --git a/templates/app/client/app/account(auth)/login/login(pug).pug b/templates/app/client/app/account(auth)/login/login(pug).pug index a463419d4..4ee882d65 100644 --- a/templates/app/client/app/account(auth)/login/login(pug).pug +++ b/templates/app/client/app/account(auth)/login/login(pug).pug @@ -1,16 +1,16 @@ .container .row .col-sm-12 - h1 Login + h1<% if (filters.i18nSupport) { %>(translate="LOGIN")<% } else { %>Login<% } %> p - | Accounts are reset on server restart from + | <% if (filters.i18nSupport) { %>{{'ACCOUNT_RESET_MSG' | translate}}<% } else { %>Accounts are reset on server restart from<% } %> code server/config/seed.js - | . Default account is + | . <% if (filters.i18nSupport) { %>{{'DEFAUL_ACCOUNT_MSG' | translate}}<% } else { %>Default account is<% } %> code test@example.com | / code test p - | Admin account is + | <% if (filters.i18nSupport) { %>{{'ADMIN_ACCOUNT_IS_MSG' | translate}}<% } else { %>Admin account is<% } %> code admin@example.com | / code admin @@ -18,23 +18,23 @@ .col-sm-12 form.form(name='form', ng-submit='vm.login(form)', novalidate='') .form-group - label Email + label<% if (filters.i18nSupport) { %>(translate="EMAIL")<% } else { %>Email<% } %> input.form-control(type='email', name='email', ng-model='vm.user.email') .form-group - label Password + label<% if (filters.i18nSupport) { %>(translate="PASSWORD")<% } else { %>Password<% } %> input.form-control(type='password', name='password', ng-model='vm.user.password') .form-group.has-error - p.help-block(ng-show='form.email.$error.required && form.password.$error.required && vm.submitted') - | Please enter your email and password. - p.help-block {{ vm.errors.login }} + p.help-block(ng-show='form.email.$error.required && form.password.$error.required && vm.submitted'<% if (filters.i18nSupport) { %> translate="ENTER_EMAIL_PASSWORD_MSG"<% } %>) + | <% if (!filters.i18nSupport) { %>Please enter your email and password.<% } %> + p.help-block {{ vm.errors.login <% if (filters.i18nSupport) { %> | translate<% } %>}} div - button.btn.btn-inverse.btn-lg.btn-login(type='submit') - | Login + button.btn.btn-inverse.btn-lg.btn-login(type='submit'<% if (filters.i18nSupport) { %> translate="LOGIN"<% } %>) + | <% if (!filters.i18nSupport) { %>Login<% } %> = ' ' - a.btn.btn-default.btn-lg.btn-register(<% if (filters.uirouter) { %>ui-sref='signup'<% } else { %>href='/signup'<% } %>) - | Register + a.btn.btn-default.btn-lg.btn-register(<% if (filters.uirouter) { %>ui-sref='signup'<% } else { %>href='/signup'<% } %><% if (filters.i18nSupport) { %> translate="REGISTER"<% } %>) + | <% if (!filters.i18nSupport) { %>Register<% } %> <% if (filters.oauth) {%> hr diff --git a/templates/app/client/app/account(auth)/settings/settings(html).html b/templates/app/client/app/account(auth)/settings/settings(html).html index 690b0cf3f..2b98dffa8 100644 --- a/templates/app/client/app/account(auth)/settings/settings(html).html +++ b/templates/app/client/app/account(auth)/settings/settings(html).html @@ -1,13 +1,13 @@
-

Change Password

+ translate="CHANGE_PASSWORD"<% } %>><% if (!filters.i18nSupport) { %>Change Password<% } %>
- + translate="CURRENT_PASSWORD"<% } %>><% if (!filters.i18nSupport) { %>Current Password<% } %> @@ -17,34 +17,34 @@

Change Password

- + translate="NEW_PASSWORD"<% } %>><% if (!filters.i18nSupport) { %>New Password<% } %>

- Password must be at least 3 characters. + ng-show="(form.newPassword.$error.minlength || form.newPassword.$error.required) && (form.newPassword.$dirty || vm.submitted)"<% if (filters.i18nSupport) { %> translate="PASSWORD_LENGTH_MSG"<% } %>> + <% if (!filters.i18nSupport) { %>Password must be at least 3 characters.<% } %>

- + translate="CONFIRM_NEW_PASSWORD"<% } %>><% if (!filters.i18nSupport) { %>Confirm New Password<% } %>

- Passwords must match. + ng-show="form.confirmPassword.$error.match && vm.submitted"<% if (filters.i18nSupport) { %> translate="PASSWORDS_MATCH_MSG"<% } %>> + <% if (!filters.i18nSupport) { %>Passwords must match.<% } %>

{{ vm.message }}

- +
diff --git a/templates/app/client/app/account(auth)/settings/settings(pug).pug b/templates/app/client/app/account(auth)/settings/settings(pug).pug index fc4bee87f..d028cd2e5 100644 --- a/templates/app/client/app/account(auth)/settings/settings(pug).pug +++ b/templates/app/client/app/account(auth)/settings/settings(pug).pug @@ -1,11 +1,11 @@ .container .row .col-sm-12 - h1 Change Password + h1<% if (filters.i18nSupport) { %>(translate="CHANGE_PASSWORD")<% } else { %> Change Password<% } %> .col-sm-12 form.form(name='form', ng-submit='vm.changePassword(form)', novalidate='') .form-group - label Current Password + label<% if (filters.i18nSupport) { %>(translate="CURRENT_PASSWORD")<% } else { %> Current Password<% } %> input.form-control(type='password' name='password' ng-model='vm.user.oldPassword' @@ -13,23 +13,23 @@ p.help-block(ng-show='form.password.$error.mongoose') | {{ vm.errors.other }} .form-group - label New Password + label<% if (filters.i18nSupport) { %>(translate="NEW_PASSWORD")<% } else { %> New Password<% } %> input.form-control(type='password' name='newPassword' ng-model='vm.user.newPassword' ng-minlength='3', required='') - p.help-block(ng-show='(form.newPassword.$error.minlength || form.newPassword.$error.required) && (form.newPassword.$dirty || vm.submitted)') - | Password must be at least 3 characters. + p.help-block(ng-show='(form.newPassword.$error.minlength || form.newPassword.$error.required) && (form.newPassword.$dirty || vm.submitted)'<% if (filters.i18nSupport) { %> translate="PASSWORD_LENGTH_MSG"<% } %>) + | <% if (!filters.i18nSupport) { %>Password must be at least 3 characters.<% } %> .form-group - label Confirm New Password + label<% if (filters.i18nSupport) { %>(translate="CONFIRM_NEW_PASSWORD")<% } else { %> Confirm New Password<% } %> input.form-control(type='password' name='confirmPassword' ng-model='vm.user.confirmPassword' match="vm.user.newPassword" ng-minlength='3', required='') - p.help-block(ng-show='fvm.orm.confirmPassword.$error.match && vm.submitted') - | Passwords must match. + p.help-block(ng-show='fvm.orm.confirmPassword.$error.match && vm.submitted'<% if (filters.i18nSupport) { %> translate="PASSWORDS_MATCH_MSG"<% } %>) + | <% if (!filters.i18nSupport) { %>Passwords must match.<% } %> p.help-block {{ vm.message }} - button.btn.btn-lg.btn-primary(type='submit') Save changes + button.btn.btn-lg.btn-primary(type='submit'<% if (filters.i18nSupport) { %> translate="SAVE_CHANGES"<% } %>) <% if (!filters.i18nSupport) { %>Save changes<% } %> diff --git a/templates/app/client/app/account(auth)/signup/signup(html).html b/templates/app/client/app/account(auth)/signup/signup(html).html index 6b6cad4b7..11834260d 100644 --- a/templates/app/client/app/account(auth)/signup/signup(html).html +++ b/templates/app/client/app/account(auth)/signup/signup(html).html @@ -1,75 +1,75 @@
-

Sign up

+ translate="SIGN_UP"<% } %>><% if (!filters.i18nSupport) { %>Sign up<% } %>
- + translate="NAME"<% } %>><% if (!filters.i18nSupport) { %>Name<% } %> -

- A name is required +

translate="NAME_REQUIRED_MSG"<% } %>> + <% if (!filters.i18nSupport) { %>A name is required<% } %>

- + translate="EMAIL"<% } %>><% if (!filters.i18nSupport) { %>Email<% } %> -

- Doesn't look like a valid email. +

translate="EMAIL_INVALID_FORMAT_MSG"<% } %>> + <% if (!filters.i18nSupport) { %>Doesn't look like a valid email.<% } %>

-

- What's your email address? +

translate="EMAIL_QUESTION_MSG"<% } %>> + <% if (!filters.i18nSupport) { %>What's your email address?<% } %>

- {{ vm.errors.email }} + {{ vm.errors.email <% if (filters.i18nSupport) { %>| translate <% } %>}}

- + translate="PASSWORD"<% } %>><% if (!filters.i18nSupport) { %>Password<% } %>

- Password must be at least 3 characters. + ng-show="(form.password.$error.minlength || form.password.$error.required) && vm.submitted"<% if (filters.i18nSupport) { %> translate="PASSWORD_LENGTH_MSG"<% } %>> + <% if (!filters.i18nSupport) { %>Password must be at least 3 characters.<% } %>

- {{ vm.errors.password }} + {{ vm.errors.password <% if (filters.i18nSupport) { %>| translate <% } %>}}

- + translate="CONFIRM_PASSWORD"<% } %>><% if (!filters.i18nSupport) { %>Confirm Password<% } %>

- Passwords must match. + ng-show="form.confirmPassword.$error.match && vm.submitted"<% if (filters.i18nSupport) { %> translate="PASSWORDS_MATCH_MSG"<% } %>> + <% if (!filters.i18nSupport) { %>Passwords must match.<% } %>

<% if (filters.oauth) { %> diff --git a/templates/app/client/app/account(auth)/signup/signup(pug).pug b/templates/app/client/app/account(auth)/signup/signup(pug).pug index 51480eefb..d82c894d4 100644 --- a/templates/app/client/app/account(auth)/signup/signup(pug).pug +++ b/templates/app/client/app/account(auth)/signup/signup(pug).pug @@ -1,58 +1,58 @@ .container .row .col-sm-12 - h1 Sign up + h1<% if (filters.i18nSupport) { %>(translate="SIGN_UP")<% } else { %> Sign up<% } %> .col-sm-12 form.form(name='form', ng-submit='vm.register(form)', novalidate='') .form-group(ng-class='{ "has-success": form.name.$valid && vm.submitted,\ "has-error": form.name.$invalid && vm.submitted }') - label Name + label<% if (filters.i18nSupport) { %>(translate="NAME")<% } else { %> Name<% } %> input.form-control(type='text', name='name', ng-model='vm.user.name', required='') - p.help-block(ng-show='form.name.$error.required && vm.submitted') - | A name is required + p.help-block(ng-show='form.name.$error.required && vm.submitted'<% if (filters.i18nSupport) { %> translate="NAME_REQUIRED_MSG"<% } %>) + | <% if (!filters.i18nSupport) { %>A name is required<% } %> .form-group(ng-class='{ "has-success": form.email.$valid && vm.submitted,\ "has-error": form.email.$invalid && vm.submitted }') - label Email + label<% if (filters.i18nSupport) { %>(translate="EMAIL")<% } else { %> Email<% } %> input.form-control(type='email', name='email', ng-model='vm.user.email', required='', mongoose-error='') - p.help-block(ng-show='form.email.$error.email && vm.submitted') - | Doesn't look like a valid email. - p.help-block(ng-show='form.email.$error.required && vm.submitted') - | What's your email address? + p.help-block(ng-show='form.email.$error.email && vm.submitted'<% if (filters.i18nSupport) { %> translate="EMAIL_INVALID_FORMAT_MSG"<% } %>) + | <% if (!filters.i18nSupport) { %>Doesn't look like a valid email.<% } %> + p.help-block(ng-show='form.email.$error.required && vm.submitted'<% if (filters.i18nSupport) { %> translate="EMAIL_QUESTION_MSG"<% } %>) + | <% if (!filters.i18nSupport) { %>What's your email address?<% } %> p.help-block(ng-show='form.email.$error.mongoose') - | {{ vm.errors.email }} + | {{ vm.errors.email <% if (filters.i18nSupport) { %>| translate<% } %>}} .form-group(ng-class='{ "has-success": form.password.$valid && vm.submitted,\ "has-error": form.password.$invalid && vm.submitted }') - label Password + label<% if (filters.i18nSupport) { %>(translate="PASSWORD")<% } else { %> Password<% } %> input.form-control(type='password' name='password' ng-model='vm.user.password' mongoose-error='' ng-minlength='3', required='') - p.help-block(ng-show='(form.password.$error.minlength || form.password.$error.required) && vm.submitted') - | Password must be at least 3 characters. + p.help-block(ng-show='(form.password.$error.minlength || form.password.$error.required) && vm.submitted'<% if (filters.i18nSupport) { %> translate="PASSWORD_LENGTH_MSG"<% } %>) + | <% if (!filters.i18nSupport) { %>Password must be at least 3 characters.<% } %> p.help-block(ng-show='form.password.$error.mongoose') - | {{ vm.errors.password }} + | {{ vm.errors.password <% if (filters.i18nSupport) { %>| translate<% } %>}} .form-group(ng-class='{ "has-success": form.confirmPassword.$valid && vm.submitted,\ "has-error": form.confirmPassword.$invalid && vm.submitted }') - label Confirm Password + label<% if (filters.i18nSupport) { %>(translate="CONFIRM_PASSWORD")<% } else { %> Confirm Password<% } %> input.form-control(type='password' name='confirmPassword' ng-model='vm.user.confirmPassword' match="vm.user.password" ng-minlength='3', required='') - p.help-block(ng-show='form.confirmPassword.$error.match && vm.submitted') - | Passwords must match. + p.help-block(ng-show='form.confirmPassword.$error.match && vm.submitted'<% if (filters.i18nSupport) { %> translate="PASSWORDS_MATCH_MSG"<% } %>) + | <% if (!filters.i18nSupport) { %>Passwords must match.<% } %> div - button.btn.btn-inverse.btn-lg.btn-register(type='submit') - | Sign up + button.btn.btn-inverse.btn-lg.btn-register(type='submit'<% if (filters.i18nSupport) { %> translate="SIGN_UP"<% } %>) + | <% if (!filters.i18nSupport) { %>Sign up<% } %> = ' ' - a.btn.btn-default.btn-lg.btn-login(<% if (filters.uirouter) { %>ui-sref='login'<% } else { %>href='/login'<% } %>) - | Login + a.btn.btn-default.btn-lg.btn-login(<% if (filters.uirouter) { %>ui-sref='login'<% } else { %>href='/login'<% } %><% if (filters.i18nSupport) { %> translate="LOGIN"<% } %>) + | <% if (!filters.i18nSupport) { %>Login<% } %> <% if (filters.oauth) {%> hr diff --git a/templates/app/client/app/admin(auth)/admin(html).html b/templates/app/client/app/admin(auth)/admin(html).html index cbbe68a40..829829d09 100644 --- a/templates/app/client/app/admin(auth)/admin(html).html +++ b/templates/app/client/app/admin(auth)/admin(html).html @@ -1,5 +1,5 @@
-

The delete user and user index api routes are restricted to users with the 'admin' role.

+

translate="ADMIN_RESTRICT_MSG"<% } %>><% if (!filters.i18nSupport) { %>The delete user and user index api routes are restricted to users with the 'admin' role.<% } %>

  • diff --git a/templates/app/client/app/admin(auth)/admin(pug).pug b/templates/app/client/app/admin(auth)/admin(pug).pug index 7da628335..5fd0707ca 100644 --- a/templates/app/client/app/admin(auth)/admin(pug).pug +++ b/templates/app/client/app/admin(auth)/admin(pug).pug @@ -1,6 +1,6 @@ .container - p - | The delete user and user index api routes are restricted to users with the 'admin' role. + p<% if (filters.i18nSupport) { %>(translate="ADMIN_RESTRICT_MSG")<% } %> + | <% if (!filters.i18nSupport) { %>The delete user and user index api routes are restricted to users with the 'admin' role.<% } %> ul.list-group li.list-group-item(ng-repeat='user in admin.users') strong {{user.name}} diff --git a/templates/app/client/app/app(css).css b/templates/app/client/app/app(css).css index d1b63a10f..b027f3ba6 100644 --- a/templates/app/client/app/app(css).css +++ b/templates/app/client/app/app(css).css @@ -3,6 +3,7 @@ <%_ if(filters.oauth) { -%> @import '~bootstrap-social/bootstrap-social.css'; <%_ } -%> + /** * Bootstrap Fonts */ @@ -44,6 +45,11 @@ color: #000; padding: 0.2em 0; } + +<% if (filters.i18nSupport) { %> +@import '../components/i18n/flags.css'; +<% } %> + <% if(!filters.bootstrap) { %> /* Responsive: Portrait tablets and up */ @media screen and (min-width: 768px) { diff --git a/templates/app/client/app/app(less).less b/templates/app/client/app/app(less).less index 191118fbb..e68efb400 100644 --- a/templates/app/client/app/app(less).less +++ b/templates/app/client/app/app(less).less @@ -15,6 +15,9 @@ color: #000; padding: 0.2em 0; } +<% if (filters.i18nSupport) { %> +@import '../components/i18n/flags.less'; +<% } %> <% if(!filters.bootstrap) { %> /* Responsive: Portrait tablets and up */ @media screen and (min-width: 768px) { diff --git a/templates/app/client/app/app(sass).scss b/templates/app/client/app/app(sass).scss index 1f774272e..af2583592 100644 --- a/templates/app/client/app/app(sass).scss +++ b/templates/app/client/app/app(sass).scss @@ -19,6 +19,9 @@ $fa-font-path: '/assets/fonts/font-awesome/'; color: #000; padding: 0.2em 0; } +<% if (filters.i18nSupport) { %> +@import '../components/i18n/flags.scss'; +<% } %> <% if(!filters.bootstrap) { %> /* Responsive: Portrait tablets and up */ @media screen and (min-width: 768px) { diff --git a/templates/app/client/app/app(stylus).styl b/templates/app/client/app/app(stylus).styl index a38c5b193..c98f76cb0 100644 --- a/templates/app/client/app/app(stylus).styl +++ b/templates/app/client/app/app(stylus).styl @@ -16,6 +16,9 @@ $icon-font-path = '../assets/fonts/bootstrap/' color #000 margin 0.2em 0 padding 0.2em 0 +<% if (filters.i18nSupport) { %> +@import '../components/i18n/flags.styl'; +<% } %> <% if(!filters.bootstrap) { %> // Responsive: Portrait tablets and up @media screen and (min-width: 768px) diff --git a/templates/app/client/app/app.config.js b/templates/app/client/app/app.config.js index 3b3ea607b..a1dfd6e5a 100644 --- a/templates/app/client/app/app.config.js +++ b/templates/app/client/app/app.config.js @@ -1,6 +1,6 @@ 'use strict'; -export function routeConfig(<% if (filters.ngroute) { %>$routeProvider<% } if (filters.uirouter) { %>$urlRouterProvider<% } %>, $locationProvider) { +export function routeConfig(<% if (filters.ngroute) { %>$routeProvider<% } if (filters.uirouter) { %>$urlRouterProvider<% } %>, $locationProvider<% if (filters.i18nSupport) { %>, $translateProvider<% } %>) { 'ngInject'; <%_ if(filters.ngroute) { _%> $routeProvider @@ -12,4 +12,16 @@ export function routeConfig(<% if (filters.ngroute) { %>$routeProvider<% } if (f .otherwise('/');<% } %> $locationProvider.html5Mode(true); + + <% if (filters.i18nSupport) { %> + $translateProvider + .useSanitizeValueStrategy('escape') + .useLocalStorage() + .fallbackLanguage("en") + .determinePreferredLanguage() + .useStaticFilesLoader({ + 'prefix': 'components/i18n/locale-', + 'suffix': '.json' + }); +<% } %> } diff --git a/templates/app/client/app/app.js b/templates/app/client/app/app.js index cda6907e9..1614dc9ea 100644 --- a/templates/app/client/app/app.js +++ b/templates/app/client/app/app.js @@ -17,6 +17,12 @@ import uiBootstrap from 'angular-ui-bootstrap';<% } %> import 'angular-validation-match'; <% } %> +<% if (filters.i18nSupport) { %> +import i18n from 'angular-translate'; +import i18nCookie from 'angular-translate-storage-cookie'; +import i18nLocal from 'angular-translate-storage-local'; +import i18nLoader from 'angular-translate-loader-static-files'; +<% } %> import {routeConfig} from './app.config'; @@ -59,6 +65,8 @@ angular.module('<%= scriptAppName %>', [ constants, <%_ if(filters.socketio) { _%> socket,<% } %> + <% if (filters.i18nSupport) { %> + 'pascalprecht.translate',<% } %> util ]) .config(routeConfig) diff --git a/templates/app/client/app/main/main(html).html b/templates/app/client/app/main/main(html).html index 13b811715..688792ace 100644 --- a/templates/app/client/app/main/main(html).html +++ b/templates/app/client/app/main/main(html).html @@ -1,7 +1,7 @@
    -

    'Allo, 'Allo!

    -

    Kick-start your next web app with Angular Fullstack

    + translate='TITLE'<% } %>><% if (!filters.i18nSupport) { %>'Allo, 'Allo!<% } %> +

    translate='WELCOME_MSG'<% } %>><% if (!filters.i18nSupport) { %>Kick-start your next web app with Angular Fullstack<% } %>

    I'm Yeoman
    @@ -9,7 +9,13 @@

    'Allo, 'Allo!

    -

    Features:

    + <% if (filters.i18nSupport) { %> +

    {{('FEATURES' | translate) + ':'}}

    + <% } %> + <% if (!filters.i18nSupport) { %> +

    Features:

    + <% } %> + @@ -17,11 +23,16 @@

    Features:

    <% if (filters.socketio) { %> - + translate="REAL_TIME_SYNC_MSG"<% } %>><% if (!filters.i18nSupport) { %>Syncs in realtime across clients<% } %>

    - + <% if (filters.i18nSupport) { %> + + <% } %> + <% if (!filters.i18nSupport) { %> + + <% } %> - +

    <% } %> diff --git a/templates/app/client/app/main/main(pug).pug b/templates/app/client/app/main/main(pug).pug index 5084e5f22..864310efc 100644 --- a/templates/app/client/app/main/main(pug).pug +++ b/templates/app/client/app/main/main(pug).pug @@ -1,13 +1,13 @@ header#banner.hero-unit .container - h1 'Allo, 'Allo! - p.lead Kick-start your next web app with Angular Fullstack + h1<% if (filters.i18nSupport) { %>(translate='TITLE')<% } else { %> 'Allo, 'Allo!<% } %> + p.lead<% if (filters.i18nSupport) { %>(translate='WELCOME_MSG')<% } else { %> Kick-start your next web app with Angular Fullstack<% } %> img(src='assets/images/yeoman.png', alt='I\'m Yeoman') .container .row .col-lg-12 - h1.page-header Features: + h1.page-header <% if (filters.i18nSupport) { %>{{('FEATURES' | translate) + ':'}}<% } else { %>Features:<% } %> ul.nav.nav-tabs.nav-stacked.col-md-4.col-lg-4.col-sm-6(ng-repeat='thing in $ctrl.awesomeThings') li a(href='#', uib-tooltip='{{thing.info}}') @@ -15,8 +15,8 @@ header#banner.hero-unit button.close(type='button', ng-click='$ctrl.deleteThing(thing)') ×<% } %><% if (filters.socketio) { %> form.thing-form - label Syncs in realtime across clients + label<% if (filters.i18nSupport) { %>(translate="REAL_TIME_SYNC_MSG")<% } else { %> Syncs in realtime across clients<% } %> p.input-group - input.form-control(type='text', placeholder='Add a new thing here.', ng-model='$ctrl.newThing') + input.form-control(type='text', placeholder="<% if (filters.i18nSupport) { %>{{'ADD_NEW_THING_HERE'| translate}}<% } else { %>Add a new thing here.<% } %>", ng-model='$ctrl.newThing') span.input-group-btn - button.btn.btn-primary(type='submit', ng-click='$ctrl.addThing()') Add New<% } %> + button.btn.btn-primary(type='submit', ng-click='$ctrl.addThing()'<% if (filters.i18nSupport) { %> translate="ADD_NEW"<% } %>) <% if (!filters.i18nSupport) { %>Add New<% } %><% } %> diff --git a/templates/app/client/components/footer/footer(html).html b/templates/app/client/components/footer/footer(html).html index b397da2a5..6472dc6f8 100644 --- a/templates/app/client/components/footer/footer(html).html +++ b/templates/app/client/components/footer/footer(html).html @@ -1,8 +1,8 @@ diff --git a/templates/app/client/components/footer/footer(pug).pug b/templates/app/client/components/footer/footer(pug).pug index 2abb98061..0f818bfd0 100644 --- a/templates/app/client/components/footer/footer(pug).pug +++ b/templates/app/client/components/footer/footer(pug).pug @@ -2,10 +2,10 @@ p | Angular Fullstack v<%= rootGeneratorVersion() %> = ' | ' - a(href='http://angular-fullstack.github.io/') Documentation + a(href='http://angular-fullstack.github.io/'<% if (filters.i18nSupport) { %> translate="DOCUMENTATION"<% } %>) <% if (!filters.i18nSupport) { %>Documentation<% } %> = ' | ' - a(href='https://gitter.im/DaftMonk/generator-angular-fullstack') Chat on Gitter + a(href='https://gitter.im/DaftMonk/generator-angular-fullstack'<% if (filters.i18nSupport) { %> translate="CHAT_ON_GITTER"<% } %>) <% if (!filters.i18nSupport) { %>Chat on Gitter<% } %> = ' | ' - a(href='https://github.com/angular-fullstack/generator-angular-fullstack/issues?state=open') Issues + a(href='https://github.com/angular-fullstack/generator-angular-fullstack/issues?state=open'<% if (filters.i18nSupport) { %> translate="ISSUES"<% } %>) <% if (!filters.i18nSupport) { %>Issues<% } %> = ' | ' - a(href='https://opencollective.com/angular-fullstack') Donate to our Open Collective + a(href='https://opencollective.com/angular-fullstack'<% if (filters.i18nSupport) { %> translate="DONATION_MSG"<% } %>) <% if (!filters.i18nSupport) { %>Donate to our Open Collective<% } %> diff --git a/templates/app/client/components/i18n(i18nSupport)/!flags.png b/templates/app/client/components/i18n(i18nSupport)/!flags.png new file mode 100644 index 000000000..892f75e67 Binary files /dev/null and b/templates/app/client/components/i18n(i18nSupport)/!flags.png differ diff --git a/templates/app/client/components/i18n(i18nSupport)/flags(css).css b/templates/app/client/components/i18n(i18nSupport)/flags(css).css new file mode 100644 index 000000000..7cd16fc30 --- /dev/null +++ b/templates/app/client/components/i18n(i18nSupport)/flags(css).css @@ -0,0 +1,22 @@ +/*! + * Generated with CSS Flag Sprite generator (https://www.flag-sprites.com/) + */ +#locale-selector{ + display: inline-block; + float: left; + margin-left: 10px; + margin-right: 10px; + margin-top: 10px; +} +.flag { + display: inline-block; + width: 32px; + height: 32px; + background: url('/components/i18n/flags.png') no-repeat; +} +.flag.flag-gb { + background-position: -32px 0; +} +.flag.flag-fr { + background-position: 0 0; +} diff --git a/templates/app/client/components/i18n(i18nSupport)/flags(less).less b/templates/app/client/components/i18n(i18nSupport)/flags(less).less new file mode 100644 index 000000000..8086813c3 --- /dev/null +++ b/templates/app/client/components/i18n(i18nSupport)/flags(less).less @@ -0,0 +1,23 @@ + +/*! + * Generated with CSS Flag Sprite generator (https://www.flag-sprites.com/) + */ +#locale-selector { + display: inline-block; + float: left; + margin-left: 10px; + margin-right: 10px; + margin-top: 10px; +} +.flag { + display: inline-block; + width: 32px; + height: 32px; + background: url('/components/i18n/flags.png') no-repeat; +} +.flag.flag-gb { + background-position: -32px 0; +} +.flag.flag-fr { + background-position: 0 0; +} \ No newline at end of file diff --git a/templates/app/client/components/i18n(i18nSupport)/flags(sass).scss b/templates/app/client/components/i18n(i18nSupport)/flags(sass).scss new file mode 100644 index 000000000..933bb892d --- /dev/null +++ b/templates/app/client/components/i18n(i18nSupport)/flags(sass).scss @@ -0,0 +1,24 @@ +/*! + * Generated with CSS Flag Sprite generator (https://www.flag-sprites.com/) + */ + +#locale-selector { + display: inline-block; + float: left; + margin-left: 10px; + margin-right: 10px; + margin-top: 10px; +} + +.flag { + display: inline-block; + width: 32px; + height: 32px; + background: url('/components/i18n/flags.png') no-repeat; + &.flag-gb { + background-position: -32px 0; + } + &.flag-fr { + background-position: 0 0; + } +} \ No newline at end of file diff --git a/templates/app/client/components/i18n(i18nSupport)/flags(stylus).styl b/templates/app/client/components/i18n(i18nSupport)/flags(stylus).styl new file mode 100644 index 000000000..843531339 --- /dev/null +++ b/templates/app/client/components/i18n(i18nSupport)/flags(stylus).styl @@ -0,0 +1,19 @@ +/*! + * Generated with CSS Flag Sprite generator (https://www.flag-sprites.com/) + */ +#locale-selector + display inline-block + float left + margin-left 10px + margin-right 10px + margin-top 10px + +.flag + display inline-block + width 32px + height 32px + background url('/components/i18n/flags.png') no-repeat + &.flag-gb + background-position -32px 0 + &.flag-fr + background-position 0 0 \ No newline at end of file diff --git a/templates/app/client/components/i18n(i18nSupport)/locale-en.json b/templates/app/client/components/i18n(i18nSupport)/locale-en.json new file mode 100644 index 000000000..cc10dd028 --- /dev/null +++ b/templates/app/client/components/i18n(i18nSupport)/locale-en.json @@ -0,0 +1,45 @@ +{ + "ACCOUNT_RESET_MSG": "Accounts are reset on server restart from ", + "ADD_NEW": "Add New", + "ADD_NEW_THING_HERE": "Add a new thing here.", + "ADMIN": "Admin", + "ADMIN_ACCOUNT_IS_MSG": "Admin account is ", + "ADMIN_RESTRICT_MSG": "The delete user and user index api routes are restricted to users with the 'admin' role.", + "CHANGE_PASSWORD": "Change Password", + "CHAT_ON_GITTER": "Chat on Gitter", + "CONFIRM_NEW_PASSWORD": "Confirm New Password", + "CONFIRM_PASSWORD": "Confirm Password", + "CONNECT_WITH_FACEBOOK": "Connect with Facebook", + "CONNECT_WITH_GOOGLE_PLUS": "Connect with Google+", + "CONNECT_WITH_TWITTER": "Connect with Twitter", + "CURRENT_PASSWORD": "Current Password", + "DEFAUL_ACCOUNT_MSG": "Default account is ", + "DOCUMENTATION": "Documentation", + "DONATION_MSG": "Donate to our Open Collective", + "EMAIL": "Email", + "EMAIL_INVALID_FORMAT_MSG": "Doesn't look like a valid email.", + "EMAIL_IN_USE_MSG": "The specified email address is already in use.", + "EMAIL_QUESTION_MSG": "What's your email address?", + "EMAIL_UNREGISTRED_MSG": "This email is not registered.", + "ENTER_EMAIL_PASSWORD_MSG": "Please enter your email and password.", + "ENTER_VALID_EMAIL_MSG": "Please enter a valid email.", + "FEATURES": "Features", + "HELLO": "Hello", + "HOME": "Home", + "ISSUES": "Issues", + "LOGIN": "Login", + "LOGOUT": "Logout", + "NAME": "Name", + "NAME_REQUIRED_MSG": "A name is required", + "NEW_PASSWORD": "New Password", + "PASSWORD": "Password", + "PASSWORDS_MATCH_MSG": "Passwords must match.", + "PASSWORD_INVALID_MSG": "This password is not correct.", + "PASSWORD_LENGTH_MSG": "Password must be at least 3 characters.", + "REAL_TIME_SYNC_MSG": "Syncs in realtime across clients", + "REGISTER": "Register", + "SAVE_CHANGES": "Save changes", + "SIGN_UP": "Sign up", + "TITLE": "Hello, Hello!", + "WELCOME_MSG": "Kick-start your next web app with Angular Fullstack" +} \ No newline at end of file diff --git a/templates/app/client/components/i18n(i18nSupport)/locale-fr.json b/templates/app/client/components/i18n(i18nSupport)/locale-fr.json new file mode 100644 index 000000000..adf98cebb --- /dev/null +++ b/templates/app/client/components/i18n(i18nSupport)/locale-fr.json @@ -0,0 +1,45 @@ +{ + "ACCOUNT_RESET_MSG": "Les comptes sont réinitialisés au redémarrage du serveur à partir de ", + "ADD_NEW": "Ajouter", + "ADD_NEW_THING_HERE": "Ajouter un nouvel item ici.", + "ADMIN": "Administration", + "ADMIN_ACCOUNT_IS_MSG": "Le compte administrateur est ", + "ADMIN_RESTRICT_MSG": "Les routes d'api 'user index' et 'delete user' sont limités aux utilisateurs ayant le rôle 'admin'.", + "CHANGE_PASSWORD": "Modification du mot de passe", + "CHAT_ON_GITTER": "Clavarder sur Gitter", + "CONFIRM_NEW_PASSWORD": "Confirmer le nouveau mot de passe", + "CONFIRM_PASSWORD": "Confirmation du mot de passe", + "CONNECT_WITH_FACEBOOK": "Se connecter avec Facebook", + "CONNECT_WITH_GOOGLE_PLUS": "Se connecter avec Google+", + "CONNECT_WITH_TWITTER": "Se connecter avec Twitter", + "CURRENT_PASSWORD": "Mot de passe actuel", + "DEFAUL_ACCOUNT_MSG": "Le compte par défaut est ", + "DOCUMENTATION": "Documentation", + "DONATION_MSG": "Faire un don à notre collectif ouvert", + "EMAIL": "Courriel", + "EMAIL_INVALID_FORMAT_MSG": "Ca ne ressemble pas à un courriel valide.", + "EMAIL_IN_USE_MSG": "L'adresse courriel spécifiée est déjà utilisée.", + "EMAIL_QUESTION_MSG": "Quelle est votre adresse courriel?", + "EMAIL_UNREGISTRED_MSG": "Ce courriel n'est pas enregistré.", + "ENTER_EMAIL_PASSWORD_MSG": "Veuillez saisir votre adresse courriel et votre mot de passe.", + "ENTER_VALID_EMAIL_MSG": "Veuillez saisir une adresse courriel valide.", + "FEATURES": "Caractéristiques", + "HELLO": "Bonjour", + "HOME": "Accueil", + "ISSUES": "Anomalies", + "LOGIN": "Connection", + "LOGOUT": "Déconnection", + "NAME": "Nom", + "NAME_REQUIRED_MSG": "Un nom est requis", + "NEW_PASSWORD": "Nouveau mot de passe", + "PASSWORD": "Mot de passe", + "PASSWORDS_MATCH_MSG": "Les mots de passe doivent correspondre.", + "PASSWORD_INVALID_MSG": "Ce mot de passe est incorrect.", + "PASSWORD_LENGTH_MSG": "Le mot de passe doit contenir au moins 3 caractères.", + "REAL_TIME_SYNC_MSG": "Synchronisation en temps réel sur les clients", + "REGISTER": "Enregistrer", + "SAVE_CHANGES": "Savegarder les changements", + "SIGN_UP": "Inscription", + "TITLE": "Bonjour, Bonjour!", + "WELCOME_MSG": "Démarrez votre prochaine application Web avec Angular Fullstack" +} \ No newline at end of file diff --git a/templates/app/client/components/navbar/navbar(html).html b/templates/app/client/components/navbar/navbar(html).html index 79d7b5a78..2ba10f5fd 100644 --- a/templates/app/client/components/navbar/navbar(html).html +++ b/templates/app/client/components/navbar/navbar(html).html @@ -1,6 +1,12 @@
    + <% if (filters.i18nSupport) { %> +
    + + +
    + <% } %>
    diff --git a/templates/app/client/components/navbar/navbar(pug).pug b/templates/app/client/components/navbar/navbar(pug).pug index cd32fb74f..38e5b4f79 100644 --- a/templates/app/client/components/navbar/navbar(pug).pug +++ b/templates/app/client/components/navbar/navbar(pug).pug @@ -1,6 +1,11 @@ div.navbar.navbar-default.navbar-static-top div.container div.navbar-header + <% if (filters.i18nSupport) { %> + #locale-selector + a.flag.flag-fr.locale-selector(ng-show="$ctrl.currentLocale!='fr'", href='', alt='Francais', ng-click="$ctrl.changeLocale('fr')") + a.flag.flag-gb.locale-selector(ng-show="$ctrl.currentLocale!='en'", href='', alt='English', ng-click="$ctrl.changeLocale('en')") + <% } %> button.navbar-toggle(type='button', ng-click='$ctrl.isCollapsed = !$ctrl.isCollapsed') span.sr-only Toggle navigation span.icon-bar @@ -11,24 +16,24 @@ div.navbar.navbar-default.navbar-static-top div#navbar-main.navbar-collapse.collapse(uib-collapse='$ctrl.isCollapsed') ul.nav.navbar-nav li(ng-repeat='item in $ctrl.menu', <% if (filters.uirouter) { %>ui-sref-active='active'<% } else { %>ng-class='{active: $ctrl.isActive(item.link)}'<% } %>) - a(<% if (filters.uirouter) { %>ui-sref='{{item.state}}'<% } else { %>ng-href='{{item.link}}'<% } %>) {{item.title}}<% if (filters.auth) { %> + a(<% if (filters.uirouter) { %>ui-sref='{{item.state}}'<% } else { %>ng-href='{{item.link}}'<% } %>) {{item.title<% if (filters.i18nSupport) { %> | translate<% } %>}}<% if (filters.auth) { %> li(ng-show='$ctrl.isAdmin()', <% if (filters.uirouter) { %>ui-sref-active='active'<% } else { %>ng-class='{active: $ctrl.isActive("/admin")}'<% } %>) - a(<% if (filters.uirouter) { %>ui-sref='admin'<% } else { %>href='/admin'<% } %>) Admin + a(<% if (filters.uirouter) { %>ui-sref='admin'<% } else { %>href='/admin'<% } %><% if (filters.i18nSupport) { %> translate="ADMIN"<% } %>) <% if (!filters.i18nSupport) { %>Admin<% } %> ul.nav.navbar-nav.navbar-right li(ng-hide='$ctrl.isLoggedIn()', <% if (filters.uirouter) { %>ui-sref-active='active'<% } else { %>ng-class='{active: $ctrl.isActive("/signup")}'<% } %>) - a(<% if (filters.uirouter) { %>ui-sref='signup'<% } else { %>href='/signup'<% } %>) Sign up + a(<% if (filters.uirouter) { %>ui-sref='signup'<% } else { %>href='/signup'<% } %><% if (filters.i18nSupport) { %> translate="SIGN_UP"<% } %>) <% if (!filters.i18nSupport) { %>Sign up<% } %> li(ng-hide='$ctrl.isLoggedIn()', <% if (filters.uirouter) { %>ui-sref-active='active'<% } else { %>ng-class='{active: $ctrl.isActive("/login")}'<% } %>) - a(<% if (filters.uirouter) { %>ui-sref='login'<% } else { %>href='/login'<% } %>) Login + a(<% if (filters.uirouter) { %>ui-sref='login'<% } else { %>href='/login'<% } %><% if (filters.i18nSupport) { %> translate="LOGIN"<% } %>) <% if (!filters.i18nSupport) { %>Login<% } %> li(ng-show='$ctrl.isLoggedIn()') - p.navbar-text Hello {{ $ctrl.getCurrentUser().name }} + p.navbar-text {{<% if (filters.i18nSupport) { %>('HELLO' | translate)<% } else { %>'Hello'<% } %> + ' ' + $ctrl.getCurrentUser().name }} li(ng-show='$ctrl.isLoggedIn()', <% if (filters.uirouter) { %>ui-sref-active='active'<% } else { %>ng-class='{active: $ctrl.isActive("/settings")}'<% } %>) a(<% if (filters.uirouter) { %>ui-sref='settings'<% } else { %>href='/settings'<% } %>) span.glyphicon.glyphicon-cog li(ng-show='$ctrl.isLoggedIn()') - a(<% if (filters.uirouter) { %>ui-sref='logout'<% } else { %>href='/logout'<% } %>) Logout<% } %> + a(<% if (filters.uirouter) { %>ui-sref='logout'<% } else { %>href='/logout'<% } %><% if (filters.i18nSupport) { %> translate="LOGOUT"<% } %>) <% if (!filters.i18nSupport) { %>Logout<% } %><% } %> diff --git a/templates/app/client/components/navbar/navbar.component.js b/templates/app/client/components/navbar/navbar.component.js index 8cf2ab0b1..1ccec7388 100644 --- a/templates/app/client/components/navbar/navbar.component.js +++ b/templates/app/client/components/navbar/navbar.component.js @@ -4,36 +4,56 @@ import angular from 'angular'; export class NavbarComponent { menu = [{ - 'title': 'Home', + <% if (filters.i18nSupport) { %>'title': 'HOME'<% } else { %>'title': 'Home'<% } %>, <% if (filters.uirouter) { %>'state': 'main'<% } else { %>'link': '/'<% } %> }]; <%_ if(!filters.uirouter) { -%> $location; <%_ } -%> + <%_ if(filters.i18nSupport) { -%> + $translate; + currentLocale; + <%_ } -%> <%_ if (filters.auth) { -%> isLoggedIn: Function; isAdmin: Function; getCurrentUser: Function; <%_ } -%> isCollapsed = true; - <%_ if(filters.ngroute || filters.auth) { _%> + <%_ if(filters.ngroute || filters.auth || filters.i18nSupport) { _%> - constructor(<% if(!filters.uirouter) { %>$location<% } if(!filters.uirouter && filters.auth) { %>, <% } if (filters.auth) { %>Auth<% } %>) { + constructor(<% if(!filters.uirouter) { %>$location<% } if(!filters.uirouter && filters.auth) { %>, <% } + if (filters.auth) { %>Auth<% } if (filters.i18nSupport && (!filters.uirouter || filters.auth)) { %>, <% } if (filters.i18nSupport) { %>$translate<% } %>) { + 'ngInject'; <%_ if(!filters.uirouter) { _%> this.$location = $location; <%_ } _%> + + <%_ if(filters.i18nSupport) { _%> + this.$translate = $translate; + this.currentLocale = $translate.proposedLanguage(); + <%_ } _%> + <%_ if (filters.auth) { _%> this.isLoggedIn = Auth.isLoggedInSync; this.isAdmin = Auth.isAdminSync; this.getCurrentUser = Auth.getCurrentUserSync; <%_ } _%> + }<% } %> - <%_ if(!filters.uirouter) { _%> + <%_ if(!filters.uirouter) { _%> isActive(route) { return route === this.$location.path(); }<% } %> + + <%_ if (filters.i18nSupport) { _%> + changeLocale(localeKey){ + this.$translate.use(localeKey); + this.currentLocale = localeKey; + } + <%_ } _%> } export default angular.module('directives.navbar', []) diff --git a/templates/app/client/components/oauth-buttons(oauth)/oauth-buttons(html).html b/templates/app/client/components/oauth-buttons(oauth)/oauth-buttons(html).html index 5ea19425f..1fceb909f 100644 --- a/templates/app/client/components/oauth-buttons(oauth)/oauth-buttons(html).html +++ b/templates/app/client/components/oauth-buttons(oauth)/oauth-buttons(html).html @@ -1,12 +1,12 @@ <% if(filters.facebookAuth) { %> - Connect with Facebook + translate="CONNECT_WITH_FACEBOOK"<% } %>><% if (!filters.i18nSupport) { %>Connect with Facebook<% } %> <% } if (filters.googleAuth) { %> - Connect with Google+ + translate="CONNECT_WITH_GOOGLE_PLUS"<% } %>><% if (!filters.i18nSupport) { %>Connect with Google+<% } %> <% } if (filters.twitterAuth) { %> - Connect with Twitter - <% } %> + translate="CONNECT_WITH_TWITTER"<% } %>><% if (!filters.i18nSupport) { %>Connect with Twitter<% } %> + <% } %> \ No newline at end of file diff --git a/templates/app/client/components/oauth-buttons(oauth)/oauth-buttons(pug).pug b/templates/app/client/components/oauth-buttons(oauth)/oauth-buttons(pug).pug index fd5030bd7..8abf3aeb6 100644 --- a/templates/app/client/components/oauth-buttons(oauth)/oauth-buttons(pug).pug +++ b/templates/app/client/components/oauth-buttons(oauth)/oauth-buttons(pug).pug @@ -1,14 +1,14 @@ <% if(filters.facebookAuth) { %>a.btn<% if (filters.bootstrap) { %>.btn-social<% } %>.btn-facebook(ng-class='classes' ng-click='OauthButtons.loginOauth("facebook")') i.fa.fa-facebook - | Connect with Facebook + span<% if (filters.i18nSupport) { %>(translate="CONNECT_WITH_FACEBOOK")<% } else { %> Connect with Facebook<% } %> <% } if(filters.googleAuth) { %>a.btn<% if (filters.bootstrap) { %>.btn-social<% } %>.btn-google(ng-class='classes' ng-click='OauthButtons.loginOauth("google")') i.fa.fa-google-plus - | Connect with Google+ + span<% if (filters.i18nSupport) { %>(translate="CONNECT_WITH_GOOGLE_PLUS")<% } else { %> Connect with Google+<% } %> <% } if(filters.twitterAuth) { %>a.btn<% if (filters.bootstrap) { %>.btn-social<% } %>.btn-twitter(ng-class='classes' ng-click='OauthButtons.loginOauth("twitter")') i.fa.fa-twitter - | Connect with Twitter<% } %> + span<% if (filters.i18nSupport) { %>(translate="CONNECT_WITH_TWITTER")<% } else { %> Connect with Twitter<% } %><% } %> diff --git a/templates/app/server/api/user(auth)/user.model(sequelizeModels).js b/templates/app/server/api/user(auth)/user.model(sequelizeModels).js index bd5a5d37b..34a32322a 100644 --- a/templates/app/server/api/user(auth)/user.model(sequelizeModels).js +++ b/templates/app/server/api/user(auth)/user.model(sequelizeModels).js @@ -20,7 +20,11 @@ export default function(sequelize, DataTypes) { email: { type: DataTypes.STRING, unique: { - msg: 'The specified email address is already in use.' + <% if (filters.i18nSupport) { %> + msg: 'EMAIL_IN_USE_MSG' + <% } else { %> + msg: 'The specified email address is already in use.' + <% } %> }, validate: { isEmail: true diff --git a/templates/app/server/auth(auth)/local/passport.js b/templates/app/server/auth(auth)/local/passport.js index 125f482bc..1749b0bea 100644 --- a/templates/app/server/auth(auth)/local/passport.js +++ b/templates/app/server/auth(auth)/local/passport.js @@ -13,7 +13,11 @@ function localAuthenticate(User, email, password, done) { .then(user => { if(!user) { return done(null, false, { + <% if (filters.i18nSupport) { %> + message: 'EMAIL_UNREGISTRED_MSG' + <% } else { %> message: 'This email is not registered.' + <% } %> }); } user.authenticate(password, function(authError, authenticated) { @@ -21,7 +25,13 @@ function localAuthenticate(User, email, password, done) { return done(authError); } if(!authenticated) { - return done(null, false, { message: 'This password is not correct.' }); + return done(null, false, { + <% if (filters.i18nSupport) { %> + message: 'PASSWORD_INVALID_MSG' + <% } else { %> + message: 'This password is not correct.' + <% } %> + }); } else { return done(null, user); } diff --git a/test/fixtures/.yo-rc.json b/test/fixtures/.yo-rc.json index ca971c119..1cfff6c65 100644 --- a/test/fixtures/.yo-rc.json +++ b/test/fixtures/.yo-rc.json @@ -21,6 +21,7 @@ "uirouter": true, "bootstrap": true, "uibootstrap": true, + "i18nSupport": false, "socketio": true, "auth": true, "models": true,

    AltStyle によって変換されたページ (->オリジナル) /