Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat (*): Add i18n support #2534

Open
wants to merge 23 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 22 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
13 changes: 13 additions & 0 deletions src/generators/app/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,11 @@ export class Generator extends Base {
filter: val => val.toLowerCase()
}, {
type: 'confirm',
name: 'i18nSupport',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it would be simpler to just call it i18n

default: false,
message: 'Would you like to include i18n support (multi-language)?'
}, {
type: 'confirm',
name: 'bootstrap',
message: 'Would you like to include Bootstrap?'
}, {
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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'`);
Expand Down Expand Up @@ -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) {
Expand Down
1 change: 1 addition & 0 deletions src/test/fixtures/.yo-rc.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"uirouter": true,
"bootstrap": true,
"uibootstrap": true,
"i18nSupport": false,
"socketio": true,
"auth": true,
"models": true,
Expand Down
10 changes: 10 additions & 0 deletions src/test/get-expected-files.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
10 changes: 7 additions & 3 deletions src/test/main.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ const defaultOptions = {
odms: ['mongoose'],
auth: true,
oauth: [],
socketio: true
socketio: true,
i18nSupport:false
};
const TEST_DIR = __dirname;

Expand Down Expand Up @@ -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() {
Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -343,6 +346,7 @@ describe('angular-fullstack:app', function() {
odms: [],
auth: false,
oauth: [],
i18nSupport:false,
socketio: false,
bootstrap: false,
uibootstrap: false
Expand Down
5 changes: 5 additions & 0 deletions templates/app/_package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
28 changes: 14 additions & 14 deletions templates/app/client/app/account(auth)/login/login(html).html
Original file line number Diff line number Diff line change
@@ -1,42 +1,42 @@
<div class="container">
<div class="row">
<div class="col-sm-12">
<h1>Login</h1>
<p>Accounts are reset on server restart from <code>server/config/seed.js</code>. Default account is <code>[email protected]</code> / <code>test</code></p>
<p>Admin account is <code>[email protected]</code> / <code>admin</code></p>
<h1<% if (filters.i18nSupport) { %> translate="LOGIN"<% } %>><% if (!filters.i18nSupport) { %>Login<% } %></h1>
<p><% if (filters.i18nSupport) { %>{{'ACCOUNT_RESET_MSG' | translate}}<% } else { %>Accounts are reset on server restart from<% } %> <code>server/config/seed.js</code>. <% if (filters.i18nSupport) { %>{{'DEFAUL_ACCOUNT_MSG' | translate}}<% } else { %>Default account is<% } %> <code>[email protected]</code> / <code>test</code></p>
<p><% if (filters.i18nSupport) { %>{{'ADMIN_ACCOUNT_IS_MSG' | translate}}<% } else { %>Admin account is<% } %> <code>[email protected]</code> / <code>admin</code></p>
</div>
<div class="col-sm-12">
<form class="form" name="form" ng-submit="vm.login(form)" novalidate>

<div class="form-group">
<label>Email</label>
<label<% if (filters.i18nSupport) { %> translate="EMAIL"<% } %>><% if (!filters.i18nSupport) { %>Email<% } %></label>

<input type="email" name="email" class="form-control" ng-model="vm.user.email" required>
</div>

<div class="form-group">
<label>Password</label>
<label<% if (filters.i18nSupport) { %> translate="PASSWORD"<% } %>><% if (!filters.i18nSupport) { %>Password<% } %></label>

<input type="password" name="password" class="form-control" ng-model="vm.user.password" required>
</div>

<div class="form-group has-error">
<p class="help-block" ng-show="form.email.$error.required && form.password.$error.required && vm.submitted">
Please enter your email and password.
<p class="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>
<p class="help-block" ng-show="form.email.$error.email && vm.submitted">
Please enter a valid email.
<p class="help-block" ng-show="form.email.$error.email && vm.submitted"<% if (filters.i18nSupport) { %> translate="ENTER_VALID_EMAIL_MSG"<% } %>>
<% if (!filters.i18nSupport) { %>Please enter a valid email.<% } %>
</p>

<p class="help-block">{{ vm.errors.login }}</p>
<p class="help-block">{{ vm.errors.login <% if (filters.i18nSupport) { %> | translate<% } %>}}</p>
</div>

<div>
<button class="btn btn-inverse btn-lg btn-login" type="submit">
Login
<button class="btn btn-inverse btn-lg btn-login" type="submit"<% if (filters.i18nSupport) { %> translate="LOGIN"<% } %>>
<% if (!filters.i18nSupport) { %>Login<% } %>
</button>
<a class="btn btn-default btn-lg btn-register" <% if (filters.uirouter) { %>ui-sref="signup"<% } else { %>href="/signup"<% } %>>
Register
<a class="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<% } %>
</a>
</div>
<% if (filters.oauth) { %>
Expand Down
26 changes: 13 additions & 13 deletions templates/app/client/app/account(auth)/login/login(pug).pug
Original file line number Diff line number Diff line change
@@ -1,40 +1,40 @@
.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 [email protected]
| /
code test
p
| Admin account is
| <% if (filters.i18nSupport) { %>{{'ADMIN_ACCOUNT_IS_MSG' | translate}}<% } else { %>Admin account is<% } %>
code [email protected]
| /
code admin

.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

Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
<div class="container">
<div class="row">
<div class="col-sm-12">
<h1>Change Password</h1>
<h1<% if (filters.i18nSupport) { %> translate="CHANGE_PASSWORD"<% } %>><% if (!filters.i18nSupport) { %>Change Password<% } %></h1>
</div>
<div class="col-sm-12">
<form class="form" name="form" ng-submit="vm.changePassword(form)" novalidate>

<div class="form-group">
<label>Current Password</label>
<label<% if (filters.i18nSupport) { %> translate="CURRENT_PASSWORD"<% } %>><% if (!filters.i18nSupport) { %>Current Password<% } %></label>

<input type="password" name="password" class="form-control" ng-model="vm.user.oldPassword"
mongoose-error/>
Expand All @@ -17,34 +17,34 @@ <h1>Change Password</h1>
</div>

<div class="form-group">
<label>New Password</label>
<label<% if (filters.i18nSupport) { %> translate="NEW_PASSWORD"<% } %>><% if (!filters.i18nSupport) { %>New Password<% } %></label>

<input type="password" name="newPassword" class="form-control" ng-model="vm.user.newPassword"
ng-minlength="3"
required/>
<p class="help-block"
ng-show="(form.newPassword.$error.minlength || form.newPassword.$error.required) && (form.newPassword.$dirty || vm.submitted)">
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.<% } %>
</p>
</div>

<div class="form-group">
<label>Confirm New Password</label>
<label<% if (filters.i18nSupport) { %> translate="CONFIRM_NEW_PASSWORD"<% } %>><% if (!filters.i18nSupport) { %>Confirm New Password<% } %></label>

<input type="password" name="confirmPassword" class="form-control" ng-model="vm.user.confirmPassword"
match="vm.user.newPassword"
ng-minlength="3"
required=""/>
<p class="help-block"
ng-show="form.confirmPassword.$error.match && vm.submitted">
Passwords must match.
ng-show="form.confirmPassword.$error.match && vm.submitted"<% if (filters.i18nSupport) { %> translate="PASSWORDS_MATCH_MSG"<% } %>>
<% if (!filters.i18nSupport) { %>Passwords must match.<% } %>
</p>

</div>

<p class="help-block"> {{ vm.message }} </p>

<button class="btn btn-lg btn-primary" type="submit">Save changes</button>
<button class="btn btn-lg btn-primary" type="submit"<% if (filters.i18nSupport) { %> translate="SAVE_CHANGES"<% } %>><% if (!filters.i18nSupport) { %>Save changes<% } %></button>
</form>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,35 +1,35 @@
.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'
mongoose-error='')
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<% } %>