From bf940b177c7665a42f0940f6860c6c7d96ea473e Mon Sep 17 00:00:00 2001 From: Emanuel Schuetze Date: Mon, 30 Nov 2015 23:52:42 +0100 Subject: [PATCH 1/2] Fixed gettext strings in JavaScript. - Added browser lanugage detection. - Use gettextCatalog.getString(..) instead of gettext(..) in JS code. - updated pot file --- openslides/agenda/static/js/agenda/site.js | 5 +- .../assignments/static/js/assignments/site.js | 45 +++++------ openslides/core/static/js/core/site.js | 31 ++++++-- openslides/core/static/templates/index.html | 2 +- .../locale/angular-gettext/template-en.pot | 74 +++++++++++-------- .../mediafiles/static/js/mediafiles/site.js | 5 +- openslides/motions/static/js/motions/site.js | 41 +++++----- openslides/users/static/js/users/site.js | 43 +++++------ 8 files changed, 139 insertions(+), 107 deletions(-) diff --git a/openslides/agenda/static/js/agenda/site.js b/openslides/agenda/static/js/agenda/site.js index c09c64140..4cb399c9b 100644 --- a/openslides/agenda/static/js/agenda/site.js +++ b/openslides/agenda/static/js/agenda/site.js @@ -6,11 +6,12 @@ angular.module('OpenSlidesApp.agenda.site', ['OpenSlidesApp.agenda']) .config([ 'mainMenuProvider', - function (mainMenuProvider) { + 'gettext', + function (mainMenuProvider, gettext) { mainMenuProvider.register({ 'ui_sref': 'agenda.item.list', 'img_class': 'calendar-o', - 'title': 'Agenda', + 'title': gettext('Agenda'), 'weight': 200, 'perm': 'agenda.can_see', }); diff --git a/openslides/assignments/static/js/assignments/site.js b/openslides/assignments/static/js/assignments/site.js index dace872e5..617dcdf46 100644 --- a/openslides/assignments/static/js/assignments/site.js +++ b/openslides/assignments/static/js/assignments/site.js @@ -6,11 +6,12 @@ angular.module('OpenSlidesApp.assignments.site', ['OpenSlidesApp.assignments']) .config([ 'mainMenuProvider', - function (mainMenuProvider) { + 'gettext', + function (mainMenuProvider, gettext) { mainMenuProvider.register({ 'ui_sref': 'assignments.assignment.list', 'img_class': 'pie-chart', - 'title': 'Elections', + 'title': gettext('Elections'), 'weight': 400, 'perm': 'assignments.can_see' }); @@ -64,8 +65,8 @@ angular.module('OpenSlidesApp.assignments.site', ['OpenSlidesApp.assignments']) // Provide generic assignment form fields for create and update view .factory('AssignmentFormFieldFactory', [ - 'gettext', - function (gettext) { + 'gettextCatalog', + function (gettextCatalog) { return { getFormFields: function () { return [ @@ -73,7 +74,7 @@ angular.module('OpenSlidesApp.assignments.site', ['OpenSlidesApp.assignments']) key: 'title', type: 'input', templateOptions: { - label: gettext('Title'), + label: gettextCatalog.getString('Title'), required: true } }, @@ -81,14 +82,14 @@ angular.module('OpenSlidesApp.assignments.site', ['OpenSlidesApp.assignments']) key: 'description', type: 'textarea', templateOptions: { - label: gettext('Description') + label: gettextCatalog.getString('Description') } }, { key: 'open_posts', type: 'input', templateOptions: { - label: gettext('Number of members to be elected'), + label: gettextCatalog.getString('Number of members to be elected'), type: 'number', required: true } @@ -97,7 +98,7 @@ angular.module('OpenSlidesApp.assignments.site', ['OpenSlidesApp.assignments']) key: 'poll_description_default', type: 'input', templateOptions: { - label: gettext('Default comment on the ballot paper') + label: gettextCatalog.getString('Default comment on the ballot paper') } }]; } @@ -107,8 +108,8 @@ angular.module('OpenSlidesApp.assignments.site', ['OpenSlidesApp.assignments']) // Provide generic assignmentpoll form fields for create and update view .factory('AssignmentPollFormFieldFactory', [ - 'gettext', - function (gettext) { + 'gettextCatalog', + function (gettextCatalog) { return { getFormFields: function () { return [ @@ -116,14 +117,14 @@ angular.module('OpenSlidesApp.assignments.site', ['OpenSlidesApp.assignments']) key: 'description', type: 'input', templateOptions: { - label: gettext('Comment on the ballot paper') + label: gettextCatalog.getString('Comment on the ballot paper') } }, { key: 'yes', type: 'input', templateOptions: { - label: gettext('Yes'), + label: gettextCatalog.getString('Yes'), type: 'number', required: true } @@ -132,7 +133,7 @@ angular.module('OpenSlidesApp.assignments.site', ['OpenSlidesApp.assignments']) key: 'poll_description_default', type: 'input', templateOptions: { - label: gettext('Default comment on the ballot paper') + label: gettextCatalog.getString('Default comment on the ballot paper') } }]; } @@ -394,11 +395,11 @@ angular.module('OpenSlidesApp.assignments.site', ['OpenSlidesApp.assignments']) .controller('AssignmentPollUpdateCtrl', [ '$scope', '$state', - 'gettext', + 'gettextCatalog', 'AssignmentPoll', 'assignmentpoll', 'ballot', - function($scope, $state, gettext, AssignmentPoll, assignmentpoll, ballot) { + function($scope, $state, gettextCatalog, AssignmentPoll, assignmentpoll, ballot) { // set initial values for form model $scope.model = assignmentpoll; $scope.ballot = ballot; @@ -415,7 +416,7 @@ angular.module('OpenSlidesApp.assignments.site', ['OpenSlidesApp.assignments']) key: 'yes_' + option.candidate_id, type: 'input', templateOptions: { - label: gettext('Yes'), + label: gettextCatalog.getString('Yes'), type: 'number', required: true } @@ -424,7 +425,7 @@ angular.module('OpenSlidesApp.assignments.site', ['OpenSlidesApp.assignments']) key: 'no_' + option.candidate_id, type: 'input', templateOptions: { - label: gettext('No'), + label: gettextCatalog.getString('No'), type: 'number', required: true } @@ -433,7 +434,7 @@ angular.module('OpenSlidesApp.assignments.site', ['OpenSlidesApp.assignments']) key:'abstain_' + option.candidate_id, type: 'input', templateOptions: { - label: gettext('Abstain'), + label: gettextCatalog.getString('Abstain'), type: 'number', required: true } @@ -457,7 +458,7 @@ angular.module('OpenSlidesApp.assignments.site', ['OpenSlidesApp.assignments']) key: 'votesvalid', type: 'input', templateOptions: { - label: gettext('Votes valid'), + label: gettextCatalog.getString('Votes valid'), type: 'number' } }, @@ -465,7 +466,7 @@ angular.module('OpenSlidesApp.assignments.site', ['OpenSlidesApp.assignments']) key: 'votesinvalid', type: 'input', templateOptions: { - label: gettext('Votes invalid'), + label: gettextCatalog.getString('Votes invalid'), type: 'number' } }, @@ -473,7 +474,7 @@ angular.module('OpenSlidesApp.assignments.site', ['OpenSlidesApp.assignments']) key: 'votescast', type: 'input', templateOptions: { - label: gettext('Votes cast'), + label: gettextCatalog.getString('Votes cast'), type: 'number' } }, @@ -483,7 +484,7 @@ angular.module('OpenSlidesApp.assignments.site', ['OpenSlidesApp.assignments']) key: 'description', type: 'input', templateOptions: { - label: gettext('Comment on the ballot paper') + label: gettextCatalog.getString('Comment on the ballot paper') } } ); diff --git a/openslides/core/static/js/core/site.js b/openslides/core/static/js/core/site.js index f25894413..ce1a1f7e5 100644 --- a/openslides/core/static/js/core/site.js +++ b/openslides/core/static/js/core/site.js @@ -63,20 +63,41 @@ angular.module('OpenSlidesApp.core.site', [ } ]) +// set browser language as default language for OpenSlides +.run([ + 'gettextCatalog', + function(gettextCatalog) { + // detect browser language + var lang = navigator.language || navigator.userLanguage; + if (lang.indexOf('-') !== -1) + lang = lang.split('-')[0]; + if (lang.indexOf('_') !== -1) + lang = lang.split('_')[0]; + // set default language + gettextCatalog.setCurrentLanguage(lang); + // load language file + if (lang != 'en') { + gettextCatalog.loadRemote("static/i18n/" + lang + ".json"); + } + //TODO: for debug only! (helps to find untranslated strings by adding "[MISSING]:") + gettextCatalog.debug = false; + } +]) .config([ 'mainMenuProvider', - function (mainMenuProvider) { + 'gettext', + function (mainMenuProvider, gettext) { mainMenuProvider.register({ 'ui_sref': 'dashboard', 'img_class': 'home', - 'title': 'Home', + 'title': gettext('Home'), 'weight': 100, }); mainMenuProvider.register({ 'ui_sref': 'config', 'img_class': 'cog', - 'title': 'Settings', + 'title': gettext('Settings'), 'weight': 1000, 'perm': 'core.can_manage_config', }); @@ -342,10 +363,6 @@ angular.module('OpenSlidesApp.core.site', [ .controller("LanguageCtrl", function ($scope, gettextCatalog) { // controller to switch app language - // TODO: detect browser language for default language - gettextCatalog.setCurrentLanguage('en'); - //TODO: for debug only! (helps to find untranslated strings by adding "[MISSING]:") - gettextCatalog.debug = true; $scope.switchLanguage = function (lang) { gettextCatalog.setCurrentLanguage(lang); if (lang != 'en') { diff --git a/openslides/core/static/templates/index.html b/openslides/core/static/templates/index.html index c8c43a6cd..7e5af8326 100644 --- a/openslides/core/static/templates/index.html +++ b/openslides/core/static/templates/index.html @@ -137,7 +137,7 @@
  • - {{ element.title }} + {{ element.title | translate }} diff --git a/openslides/locale/angular-gettext/template-en.pot b/openslides/locale/angular-gettext/template-en.pot index 90258a413..e37f4e2f5 100644 --- a/openslides/locale/angular-gettext/template-en.pot +++ b/openslides/locale/angular-gettext/template-en.pot @@ -20,13 +20,13 @@ msgstr "" msgid "--- Select state ---" msgstr "" -#: users/static/js/users/site.js:322 +#: users/static/js/users/site.js:323 #: users/static/templates/users/user-detail-profile.html:39 #: users/static/templates/users/user-detail.html:37 msgid "About me" msgstr "" -#: assignments/static/js/assignments/site.js:436 +#: assignments/static/js/assignments/site.js:437 #: motions/static/templates/motions/motion-detail.html:135 #: motions/static/templates/motions/motion-detail.html:136 #: motions/static/templates/motions/motion-detail.html:186 @@ -64,6 +64,7 @@ msgstr "" msgid "Administrative data" msgstr "" +#: agenda/static/js/agenda/site.js:14 #: agenda/static/templates/agenda/item-list.html:25 #: agenda/static/templates/agenda/item-list.html:47 #: agenda/static/templates/agenda/slide-item-list.html:2 @@ -177,14 +178,14 @@ msgid "Closed" msgstr "" #: agenda/static/templates/agenda/item-list.html:174 -#: users/static/js/users/site.js:315 +#: users/static/js/users/site.js:316 #: users/static/templates/users/user-detail.html:45 #: users/static/templates/users/user-import.html:72 msgid "Comment" msgstr "" -#: assignments/static/js/assignments/site.js:119 -#: assignments/static/js/assignments/site.js:486 +#: assignments/static/js/assignments/site.js:120 +#: assignments/static/js/assignments/site.js:487 msgid "Comment on the ballot paper" msgstr "" @@ -220,8 +221,8 @@ msgstr "" msgid "Current value:" msgstr "" -#: assignments/static/js/assignments/site.js:100 -#: assignments/static/js/assignments/site.js:135 +#: assignments/static/js/assignments/site.js:101 +#: assignments/static/js/assignments/site.js:136 msgid "Default comment on the ballot paper" msgstr "" @@ -229,7 +230,7 @@ msgstr "" msgid "Default groups" msgstr "" -#: users/static/js/users/site.js:303 +#: users/static/js/users/site.js:304 msgid "Default password" msgstr "" @@ -259,7 +260,7 @@ msgstr "" msgid "Delete selected items" msgstr "" -#: assignments/static/js/assignments/site.js:84 +#: assignments/static/js/assignments/site.js:85 #: assignments/static/templates/assignments/assignment-detail.html:37 #: core/static/templates/core/projector-controls.html:120 msgid "Description" @@ -360,10 +361,12 @@ msgstr "" msgid "Election result" msgstr "" +#: assignments/static/js/assignments/site.js:14 #: assignments/static/templates/assignments/assignment-list.html:17 msgid "Elections" msgstr "" +#: mediafiles/static/js/mediafiles/site.js:14 #: mediafiles/static/templates/mediafiles/mediafile-list.html:9 msgid "Files" msgstr "" @@ -386,7 +389,7 @@ msgstr "" msgid "Filter" msgstr "" -#: users/static/js/users/site.js:269 +#: users/static/js/users/site.js:270 #: users/static/templates/users/user-detail-profile.html:26 #: users/static/templates/users/user-import.html:68 msgid "First name" @@ -396,7 +399,7 @@ msgstr "" msgid "Group" msgstr "" -#: users/static/js/users/site.js:290 +#: users/static/js/users/site.js:291 #: users/static/templates/users/group-list.html:13 #: users/static/templates/users/user-detail.html:33 #: users/static/templates/users/user-import.html:71 @@ -418,6 +421,10 @@ msgstr "" msgid "Hide internal agenda items" msgstr "" +#: core/static/js/core/site.js:93 +msgid "Home" +msgstr "" + #: users/static/templates/users/group-list.html:34 msgid "ID" msgstr "" @@ -455,11 +462,11 @@ msgstr "" msgid "Import participants" msgstr "" -#: users/static/js/users/site.js:722 +#: users/static/js/users/site.js:723 msgid "Important: Please change your password!" msgstr "" -#: users/static/js/users/site.js:720 +#: users/static/js/users/site.js:721 msgid "Installation was successfully." msgstr "" @@ -469,11 +476,11 @@ msgstr "" msgid "Invalid votes" msgstr "" -#: users/static/js/users/site.js:337 +#: users/static/js/users/site.js:338 msgid "Is active" msgstr "" -#: users/static/js/users/site.js:330 +#: users/static/js/users/site.js:331 #: users/static/templates/users/user-list.html:70 msgid "Is present" msgstr "" @@ -482,7 +489,7 @@ msgstr "" msgid "Item number" msgstr "" -#: users/static/js/users/site.js:276 +#: users/static/js/users/site.js:277 #: users/static/templates/users/user-detail-profile.html:30 #: users/static/templates/users/user-import.html:69 msgid "Last name" @@ -597,14 +604,14 @@ msgstr "" msgid "Next speakers:" msgstr "" -#: assignments/static/js/assignments/site.js:427 +#: assignments/static/js/assignments/site.js:428 #: motions/static/templates/motions/motion-detail.html:130 #: motions/static/templates/motions/motion-detail.html:131 #: motions/static/templates/motions/motion-detail.html:177 msgid "No" msgstr "" -#: assignments/static/js/assignments/site.js:91 +#: assignments/static/js/assignments/site.js:92 #: assignments/static/templates/assignments/assignment-list.html:144 msgid "Number of members to be elected" msgstr "" @@ -634,6 +641,7 @@ msgstr "" msgid "Participant" msgstr "" +#: users/static/js/users/site.js:14 #: users/static/templates/users/user-list.html:35 msgid "Participants" msgstr "" @@ -826,7 +834,7 @@ msgstr "" msgid "Select or search a category..." msgstr "" -#: users/static/js/users/site.js:296 +#: users/static/js/users/site.js:297 msgid "Select or search a group..." msgstr "" @@ -858,6 +866,10 @@ msgstr "" msgid "Select or search an attachment..." msgstr "" +#: core/static/js/core/site.js:100 +msgid "Settings" +msgstr "" + #: mediafiles/static/templates/mediafiles/mediafile-list.html:65 #: motions/static/templates/motions/category-list.html:44 msgid "Show" @@ -909,7 +921,7 @@ msgstr "" msgid "Stop current speaker" msgstr "" -#: users/static/js/users/site.js:283 +#: users/static/js/users/site.js:284 #: users/static/templates/users/user-detail-profile.html:35 #: users/static/templates/users/user-detail.html:31 #: users/static/templates/users/user-import.html:70 @@ -953,7 +965,7 @@ msgid "Tags" msgstr "" #: agenda/static/templates/agenda/item-import.html:64 -#: core/static/js/core/site.js:413 +#: core/static/js/core/site.js:430 #: motions/static/js/motions/site.js:158 #: motions/static/templates/motions/motion-detail.html:232 msgid "Text" @@ -971,15 +983,15 @@ msgstr "" #. academic degree #: agenda/static/templates/agenda/item-import.html:63 #: agenda/static/templates/agenda/item-list.html:170 -#: assignments/static/js/assignments/site.js:76 +#: assignments/static/js/assignments/site.js:77 #: assignments/static/templates/assignments/assignment-list.html:140 #: assignments/static/templates/assignments/assignment-list.html:84 -#: core/static/js/core/site.js:405 +#: core/static/js/core/site.js:422 #: mediafiles/static/templates/mediafiles/mediafile-form.html:25 #: mediafiles/static/templates/mediafiles/mediafile-list.html:25 #: motions/static/js/motions/site.js:150 #: motions/static/templates/motions/motion-list.html:91 -#: users/static/js/users/site.js:262 +#: users/static/js/users/site.js:263 #: users/static/templates/users/user-detail-profile.html:22 #: users/static/templates/users/user-import.html:67 msgid "Title" @@ -1007,7 +1019,7 @@ msgstr "" msgid "Uploaded by" msgstr "" -#: users/static/js/users/site.js:721 +#: users/static/js/users/site.js:722 msgid "Use admin and admin for first login." msgstr "" @@ -1022,7 +1034,7 @@ msgstr "" msgid "Username" msgstr "" -#: users/static/js/users/site.js:742 +#: users/static/js/users/site.js:743 msgid "Username or password was not correct." msgstr "" @@ -1036,18 +1048,18 @@ msgstr "" msgid "Vote" msgstr "" -#: assignments/static/js/assignments/site.js:476 +#: assignments/static/js/assignments/site.js:477 #: motions/static/templates/motions/motion-detail.html:150 #: motions/static/templates/motions/motion-detail.html:151 #: motions/static/templates/motions/motion-detail.html:214 msgid "Votes cast" msgstr "" -#: assignments/static/js/assignments/site.js:468 +#: assignments/static/js/assignments/site.js:469 msgid "Votes invalid" msgstr "" -#: assignments/static/js/assignments/site.js:460 +#: assignments/static/js/assignments/site.js:461 msgid "Votes valid" msgstr "" @@ -1059,8 +1071,8 @@ msgstr "" msgid "Workflow" msgstr "" -#: assignments/static/js/assignments/site.js:126 -#: assignments/static/js/assignments/site.js:418 +#: assignments/static/js/assignments/site.js:127 +#: assignments/static/js/assignments/site.js:419 #: motions/static/templates/motions/motion-detail.html:125 #: motions/static/templates/motions/motion-detail.html:126 #: motions/static/templates/motions/motion-detail.html:168 diff --git a/openslides/mediafiles/static/js/mediafiles/site.js b/openslides/mediafiles/static/js/mediafiles/site.js index 63bd4042f..0a62c9998 100644 --- a/openslides/mediafiles/static/js/mediafiles/site.js +++ b/openslides/mediafiles/static/js/mediafiles/site.js @@ -6,11 +6,12 @@ angular.module('OpenSlidesApp.mediafiles.site', ['ngFileUpload', 'OpenSlidesApp. .config([ 'mainMenuProvider', - function (mainMenuProvider) { + 'gettext', + function (mainMenuProvider, gettext) { mainMenuProvider.register({ 'ui_sref': 'mediafiles.mediafile.list', 'img_class': 'paperclip', - 'title': 'Files', + 'title': gettext('Files'), 'weight': 600, 'perm': 'mediafiles.can_see', }); diff --git a/openslides/motions/static/js/motions/site.js b/openslides/motions/static/js/motions/site.js index 2f46ebb47..9d8c16e7c 100644 --- a/openslides/motions/static/js/motions/site.js +++ b/openslides/motions/static/js/motions/site.js @@ -109,7 +109,7 @@ angular.module('OpenSlidesApp.motions.site', ['OpenSlidesApp.motions']) // Provide generic motion form fields for create and update view .factory('MotionFormFieldFactory', [ - 'gettext', + 'gettextCatalog', 'operator', 'Category', 'Config', @@ -117,7 +117,7 @@ angular.module('OpenSlidesApp.motions.site', ['OpenSlidesApp.motions']) 'Tag', 'User', 'Workflow', - function (gettext, operator, Category, Config, Mediafile, Tag, User, Workflow) { + function (gettextCatalog, operator, Category, Config, Mediafile, Tag, User, Workflow) { return { getFormFields: function () { return [ @@ -125,7 +125,7 @@ angular.module('OpenSlidesApp.motions.site', ['OpenSlidesApp.motions']) key: 'identifier', type: 'input', templateOptions: { - label: gettext('Identifier') + label: gettextCatalog.getString('Identifier') }, hide: true }, @@ -133,13 +133,13 @@ angular.module('OpenSlidesApp.motions.site', ['OpenSlidesApp.motions']) key: 'submitters_id', type: 'ui-select-multiple', templateOptions: { - label: gettext('Submitters'), + label: gettextCatalog.getString('Submitters'), optionsAttr: 'bs-options', options: User.getAll(), ngOptions: 'option[to.valueProp] as option in to.options | filter: $select.search', valueProp: 'id', labelProp: 'full_name', - placeholder: gettext('Select or search a submitter...') + placeholder: gettextCatalog.getString('Select or search a submitter...') }, hide: !operator.hasPerms('motions.can_manage') }, @@ -147,7 +147,7 @@ angular.module('OpenSlidesApp.motions.site', ['OpenSlidesApp.motions']) key: 'title', type: 'input', templateOptions: { - label: gettext('Title'), + label: gettextCatalog.getString('Title'), required: true } }, @@ -155,7 +155,7 @@ angular.module('OpenSlidesApp.motions.site', ['OpenSlidesApp.motions']) key: 'text', type: 'textarea', templateOptions: { - label: gettext('Text'), + label: gettextCatalog.getString('Text'), required: true }, ngModelElAttrs: {'ckeditor': 'CKEditorOptions'} @@ -164,7 +164,7 @@ angular.module('OpenSlidesApp.motions.site', ['OpenSlidesApp.motions']) key: 'reason', type: 'textarea', templateOptions: { - label: gettext('Reason') + label: gettextCatalog.getString('Reason') }, ngModelElAttrs: {'ckeditor': 'CKEditorOptions'} }, @@ -172,7 +172,7 @@ angular.module('OpenSlidesApp.motions.site', ['OpenSlidesApp.motions']) key: 'more', type: 'checkbox', templateOptions: { - label: gettext('Show extended fields') + label: gettextCatalog.getString('Show extended fields') }, hide: !operator.hasPerms('motions.can_manage') }, @@ -180,13 +180,13 @@ angular.module('OpenSlidesApp.motions.site', ['OpenSlidesApp.motions']) key: 'attachments_id', type: 'ui-select-multiple', templateOptions: { - label: gettext('Attachment'), + label: gettextCatalog.getString('Attachment'), optionsAttr: 'bs-options', options: Mediafile.getAll(), ngOptions: 'option[to.valueProp] as option in to.options | filter: $select.search', valueProp: 'id', labelProp: 'title_or_filename', - placeholder: gettext('Select or search an attachment...') + placeholder: gettextCatalog.getString('Select or search an attachment...') }, hideExpression: '!model.more' }, @@ -194,13 +194,13 @@ angular.module('OpenSlidesApp.motions.site', ['OpenSlidesApp.motions']) key: 'category_id', type: 'ui-select-single', templateOptions: { - label: gettext('Category'), + label: gettextCatalog.getString('Category'), optionsAttr: 'bs-options', options: Category.getAll(), ngOptions: 'option[to.valueProp] as option in to.options | filter: $select.search', valueProp: 'id', labelProp: 'name', - placeholder: gettext('Select or search a category...') + placeholder: gettextCatalog.getString('Select or search a category...') }, hideExpression: '!model.more' }, @@ -208,13 +208,13 @@ angular.module('OpenSlidesApp.motions.site', ['OpenSlidesApp.motions']) key: 'tags_id', type: 'ui-select-multiple', templateOptions: { - label: gettext('Tags'), + label: gettextCatalog.getString('Tags'), optionsAttr: 'bs-options', options: Tag.getAll(), ngOptions: 'option[to.valueProp] as option in to.options | filter: $select.search', valueProp: 'id', labelProp: 'name', - placeholder: gettext('Select or search a tag...') + placeholder: gettextCatalog.getString('Select or search a tag...') }, hideExpression: '!model.more' }, @@ -222,13 +222,13 @@ angular.module('OpenSlidesApp.motions.site', ['OpenSlidesApp.motions']) key: 'supporters_id', type: 'ui-select-multiple', templateOptions: { - label: gettext('Supporters'), + label: gettextCatalog.getString('Supporters'), optionsAttr: 'bs-options', options: User.getAll(), ngOptions: 'option[to.valueProp] as option in to.options | filter: $select.search', valueProp: 'id', labelProp: 'full_name', - placeholder: gettext('Select or search a supporter...') + placeholder: gettextCatalog.getString('Select or search a supporter...') }, hideExpression: '!model.more' }, @@ -236,13 +236,13 @@ angular.module('OpenSlidesApp.motions.site', ['OpenSlidesApp.motions']) key: 'workflow_id', type: 'ui-select-single', templateOptions: { - label: gettext('Workflow'), + label: gettextCatalog.getString('Workflow'), optionsAttr: 'bs-options', options: Workflow.getAll(), ngOptions: 'option[to.valueProp] as option in to.options | filter: $select.search', valueProp: 'id', labelProp: 'name', - placeholder: gettext('Select or search a workflow...') + placeholder: gettextCatalog.getString('Select or search a workflow...') }, hideExpression: '!model.more', }]; @@ -504,7 +504,6 @@ angular.module('OpenSlidesApp.motions.site', ['OpenSlidesApp.motions']) .controller('MotionUpdateCtrl', [ '$scope', '$state', - 'gettext', 'Motion', 'Category', 'Config', @@ -514,7 +513,7 @@ angular.module('OpenSlidesApp.motions.site', ['OpenSlidesApp.motions']) 'User', 'Workflow', 'motion', - function($scope, $state, gettext, Motion, Category, Config, Mediafile, MotionFormFieldFactory, Tag, User, Workflow, motion) { + function($scope, $state, Motion, Category, Config, Mediafile, MotionFormFieldFactory, Tag, User, Workflow, motion) { Category.bindAll({}, $scope, 'categories'); Mediafile.bindAll({}, $scope, 'mediafiles'); Tag.bindAll({}, $scope, 'tags'); diff --git a/openslides/users/static/js/users/site.js b/openslides/users/static/js/users/site.js index 4d5ba3608..525427782 100644 --- a/openslides/users/static/js/users/site.js +++ b/openslides/users/static/js/users/site.js @@ -6,11 +6,12 @@ angular.module('OpenSlidesApp.users.site', ['OpenSlidesApp.users']) .config([ 'mainMenuProvider', - function (mainMenuProvider) { + 'gettext', + function (mainMenuProvider, gettext) { mainMenuProvider.register({ 'ui_sref': 'users.user.list', 'img_class': 'user', - 'title': 'Participants', + 'title': gettext('Participants'), 'weight': 500, 'perm': 'users.can_see_name', }); @@ -249,9 +250,9 @@ angular.module('OpenSlidesApp.users.site', ['OpenSlidesApp.users']) // Provide generic user form fields for create and update view .factory('UserFormFieldFactory', [ '$http', - 'gettext', + 'gettextCatalog', 'Group', - function ($http, gettext, Group) { + function ($http, gettextCatalog, Group) { return { getFormFields: function () { return [ @@ -259,48 +260,48 @@ angular.module('OpenSlidesApp.users.site', ['OpenSlidesApp.users']) key: 'title', type: 'input', templateOptions: { - label: gettext('Title'), + label: gettextCatalog.getString('Title'), } }, { key: 'first_name', type: 'input', templateOptions: { - label: gettext('First name') + label: gettextCatalog.getString('First name') } }, { key: 'last_name', type: 'input', templateOptions: { - label: gettext('Last name') + label: gettextCatalog.getString('Last name') } }, { key: 'structure_level', type: 'input', templateOptions: { - label: gettext('Structure level') + label: gettextCatalog.getString('Structure level') } }, { key: 'groups', type: 'ui-select-multiple', templateOptions: { - label: gettext('Groups'), + label: gettextCatalog.getString('Groups'), optionsAttr: 'bs-options', options: Group.getAll(), ngOptions: 'option[to.valueProp] as option in to.options | filter: $select.search', valueProp: 'id', labelProp: 'name', - placeholder: gettext('Select or search a group...') + placeholder: gettextCatalog.getString('Select or search a group...') } }, { key: 'default_password', type: 'input', templateOptions: { - label: gettext('Default password'), + label: gettextCatalog.getString('Default password'), addonRight: { text: 'Reset', class: 'fa fa-undo', onClick: function () { // TODO: find a way to get user.id //$http.post('/rest/users/user/' + model.id + '/reset_password/', {}) @@ -312,14 +313,14 @@ angular.module('OpenSlidesApp.users.site', ['OpenSlidesApp.users']) key: 'comment', type: 'input', templateOptions: { - label: gettext('Comment') + label: gettextCatalog.getString('Comment') } }, { key: 'about_me', type: 'textarea', templateOptions: { - label: gettext('About me') + label: gettextCatalog.getString('About me') }, ngModelElAttrs: {'ckeditor': 'CKEditorOptions'} }, @@ -327,14 +328,14 @@ angular.module('OpenSlidesApp.users.site', ['OpenSlidesApp.users']) key: 'is_present', type: 'checkbox', templateOptions: { - label: gettext('Is present') + label: gettextCatalog.getString('Is present') } }, { key: 'is_active', type: 'checkbox', templateOptions: { - label: gettext('Is active') + label: gettextCatalog.getString('Is active') } }]; } @@ -709,17 +710,17 @@ angular.module('OpenSlidesApp.users.site', ['OpenSlidesApp.users']) '$scope', '$http', 'operator', - 'gettext', + 'gettextCatalog', 'Config', - function ($scope, $http, operator, gettext, Config) { + function ($scope, $http, operator, gettextCatalog, Config) { $scope.alerts = []; // TODO: add welcome message only on first time (or if admin password not changed) $scope.alerts.push({ type: 'success', - msg: gettext("Installation was successfully.") + "
    " + - gettext("Use admin and admin for first login.") + "
    " + - gettext("Important: Please change your password!") + msg: gettextCatalog.getString("Installation was successfully.") + "
    " + + gettextCatalog.getString("Use admin and admin for first login.") + "
    " + + gettextCatalog.getString("Important: Please change your password!") }); // close alert function $scope.closeAlert = function(index) { @@ -739,7 +740,7 @@ angular.module('OpenSlidesApp.users.site', ['OpenSlidesApp.users']) } else { $scope.alerts.push({ type: 'danger', - msg: gettext('Username or password was not correct.') + msg: gettextCatalog.getString('Username or password was not correct.') }); //Username or password is not correct. } From e23121ed0f3823f65d4b7843aaad833801270569 Mon Sep 17 00:00:00 2001 From: Emanuel Schuetze Date: Tue, 1 Dec 2015 12:06:15 +0100 Subject: [PATCH 2/2] Updated language menu. - improved header menu style - define new Languages factory - make it easier to define new languages --- openslides/core/static/css/app.css | 15 ++++ openslides/core/static/js/core/site.js | 77 ++++++++++++++++----- openslides/core/static/templates/index.html | 53 ++++++-------- 3 files changed, 95 insertions(+), 50 deletions(-) diff --git a/openslides/core/static/css/app.css b/openslides/core/static/css/app.css index b3e53c316..7c4c3abd9 100644 --- a/openslides/core/static/css/app.css +++ b/openslides/core/static/css/app.css @@ -82,6 +82,16 @@ img { color: #999; } +#header a.headerlink { + text-decoration: none; +} +#header a.headerlink { + color: #999; +} +#header a.headerlink:hover, #header a.headerlink:active, #header a.headerlink.active { + color: #e8eaed; +} + #header .title { float: left; margin: 2px 0 0 -5px; @@ -716,4 +726,9 @@ tr.selected td { #nav .navbar .button i { padding-top: 15px;} #nav .searchbar { margin-top: 15px; } .searchbar .input-medium { width: 150px; } + + #chatbox { width: 100%; top: 130px; } + .optional { /* hide optional column */ + display: none; + } } diff --git a/openslides/core/static/js/core/site.js b/openslides/core/static/js/core/site.js index ce1a1f7e5..b0bcea1ee 100644 --- a/openslides/core/static/js/core/site.js +++ b/openslides/core/static/js/core/site.js @@ -66,19 +66,11 @@ angular.module('OpenSlidesApp.core.site', [ // set browser language as default language for OpenSlides .run([ 'gettextCatalog', - function(gettextCatalog) { - // detect browser language - var lang = navigator.language || navigator.userLanguage; - if (lang.indexOf('-') !== -1) - lang = lang.split('-')[0]; - if (lang.indexOf('_') !== -1) - lang = lang.split('_')[0]; - // set default language - gettextCatalog.setCurrentLanguage(lang); - // load language file - if (lang != 'en') { - gettextCatalog.loadRemote("static/i18n/" + lang + ".json"); - } + 'Languages', + function(gettextCatalog, Languages) { + // set detected browser language as default language (fallback: 'en') + Languages.setCurrentLanguage(Languages.getBrowserLanguage()); + //TODO: for debug only! (helps to find untranslated strings by adding "[MISSING]:") gettextCatalog.debug = false; } @@ -361,13 +353,62 @@ angular.module('OpenSlidesApp.core.site', [ } ]) -.controller("LanguageCtrl", function ($scope, gettextCatalog) { +// gets all in OpenSlides available languages +.factory('Languages', [ + 'gettext', + 'gettextCatalog', + function (gettext, gettextCatalog) { + return { + // get all available languages + getLanguages: function () { + var current = gettextCatalog.getCurrentLanguage(); + // Define here new languages... + var languages = [ + { code: 'en', name: gettext('English') }, + { code: 'de', name: gettext('German') }, + { code: 'fr', name: gettext('French') } + ]; + angular.forEach(languages, function (language) { + if (language.code == current) + language.selected = true; + }); + return languages + }, + // get detected browser language code + getBrowserLanguage: function () { + var lang = navigator.language || navigator.userLanguage; + if (lang.indexOf('-') !== -1) + lang = lang.split('-')[0]; + if (lang.indexOf('_') !== -1) + lang = lang.split('_')[0]; + return lang; + }, + // set current language and return updated languages object array + setCurrentLanguage: function (lang) { + var languages = this.getLanguages(); + angular.forEach(languages, function (language) { + language.selected = false; + if (language.code == lang) { + language.selected = true; + gettextCatalog.setCurrentLanguage(lang); + if (lang != 'en') { + gettextCatalog.loadRemote("static/i18n/" + lang + ".json"); + } + } + }); + return languages; + } + } + } +]) + +.controller("LanguageCtrl", function ($scope, gettextCatalog, Languages, filterFilter) { + $scope.languages = Languages.getLanguages(); + $scope.selectedLanguage = filterFilter($scope.languages, {selected: true}); // controller to switch app language $scope.switchLanguage = function (lang) { - gettextCatalog.setCurrentLanguage(lang); - if (lang != 'en') { - gettextCatalog.loadRemote("static/i18n/" + lang + ".json"); - } + $scope.languages = Languages.setCurrentLanguage(lang); + $scope.selectedLanguage = filterFilter($scope.languages, {selected: true}); }; }) diff --git a/openslides/core/static/templates/index.html b/openslides/core/static/templates/index.html index 7e5af8326..573f14312 100644 --- a/openslides/core/static/templates/index.html +++ b/openslides/core/static/templates/index.html @@ -31,13 +31,14 @@ - +