feat(i18n): add templates translation

feat807-i18n
Anthony Lapenna 7 years ago
parent ed9df4f139
commit fedad6574e

@ -100,13 +100,14 @@ angular.module('portainer', [
'outsideClick': 'outsideClick'
});
$translateProvider.useSanitizeValueStrategy('sanitize');
$translateProvider.useSanitizeValueStrategy('sanitizeParameters');
$translateProvider
.useStaticFilesLoader({
'prefix': 'i18n/',
'suffix': '.json'
});
$translateProvider.preferredLanguage('en');
$translateProvider.fallbackLanguage('en');
$stateProvider
.state('root', {

@ -1,11 +1,13 @@
<rd-header id="view-top">
<rd-header-title title="Application templates list">
<a data-toggle="tooltip" title="Refresh" ui-sref="templates" ui-sref-opts="{reload: true}">
<rd-header-title title="TEMPLATES.HEADER.TITLE">
<a data-toggle="tooltip" title="COMMON.VERBS.REFRESH" ui-sref="templates" ui-sref-opts="{reload: true}">
<i class="fa fa-refresh" aria-hidden="true"></i>
</a>
<i id="loadTemplatesSpinner" class="fa fa-cog fa-spin" style="margin-left: 5px;"></i>
</rd-header-title>
<rd-header-content>Templates</rd-header-content>
<rd-header-content>
<por-translation key="TEMPLATES.HEADER.CONTENT"></por-translation>
</rd-header-content>
</rd-header>
<div class="row" style="height: 90%">
@ -14,7 +16,9 @@
<rd-widget>
<rd-widget-custom-header icon="state.selectedTemplate.Logo" title="state.selectedTemplate.Image">
<div class="pull-right">
<button type="button" class="btn btn-sm btn-primary" ng-click="unselectTemplate()">Hide</button>
<button type="button" class="btn btn-sm btn-primary" ng-click="unselectTemplate()">
<por-translation key="COMMON.VERBS.HIDE"></por-translation>
</button>
</div>
</rd-widget-custom-header>
<rd-widget-body classes="padding">
@ -23,7 +27,7 @@
<!-- description -->
<div ng-if="state.selectedTemplate.Note">
<div class="col-sm-12 form-section-title">
Information
<por-translation key="TEMPLATES.SELECTED_TEMPLATE.TITLE_INFORMATION"></por-translation>
</div>
<div class="form-group">
<div class="col-sm-12">
@ -33,11 +37,13 @@
</div>
<!-- !description -->
<div class="col-sm-12 form-section-title">
Configuration
<por-translation key="TEMPLATES.SELECTED_TEMPLATE.TITLE_CONFIGURATION"></por-translation>
</div>
<!-- name-input -->
<div class="form-group">
<label for="container_name" class="col-sm-2 control-label text-left">Name</label>
<label for="container_name" class="col-sm-2 control-label text-left">
<por-translation key="TEMPLATES.SELECTED_TEMPLATE.FORM.NAME"></por-translation>
</label>
<div class="col-sm-10">
<input type="text" name="container_name" class="form-control" ng-model="formValues.name" placeholder="e.g. web (optional)">
</div>
@ -45,10 +51,11 @@
<!-- !name-input -->
<!-- network-input -->
<div class="form-group">
<label for="container_network" class="col-sm-2 control-label text-left">Network</label>
<label for="container_network" class="col-sm-2 control-label text-left">
<por-translation key="TEMPLATES.SELECTED_TEMPLATE.FORM.NETWORK"></por-translation>
</label>
<div class="col-sm-10">
<select class="form-control" ng-options="net.Name for net in availableNetworks" ng-model="formValues.network">
<option disabled hidden value="">Select a network</option>
</select>
</div>
</div>
@ -58,10 +65,14 @@
<label for="field_{{ $index }}" class="col-sm-2 control-label text-left">{{ var.label }}</label>
<div class="col-sm-10">
<select ng-if="applicationState.endpoint.mode.provider !== 'DOCKER_SWARM' && var.type === 'container'" ng-options="container|containername for container in runningContainers" class="form-control" ng-model="var.value">
<option selected disabled hidden value="">Select a container</option>
<option selected disabled hidden value="" translate>
TEMPLATES.SELECTED_TEMPLATE.FORM.SELECT_CONTAINER
</option>
</select>
<select ng-if="applicationState.endpoint.mode.provider === 'DOCKER_SWARM' && var.type === 'container'" ng-options="container|swarmcontainername for container in runningContainers" class="form-control" ng-model="var.value">
<option selected disabled hidden value="">Select a container</option>
<option selected disabled hidden value="" translate>
TEMPLATES.SELECTED_TEMPLATE.FORM.SELECT_CONTAINER
</option>
</select>
<input ng-if="!var.type || !var.type === 'container'" type="text" class="form-control" ng-model="var.value" id="field_{{ $index }}">
</div>
@ -73,10 +84,10 @@
<div class="form-group">
<div class="col-sm-12">
<a class="small interactive" ng-if="!state.showAdvancedOptions" ng-click="state.showAdvancedOptions = true;">
<i class="fa fa-plus space-right" aria-hidden="true"></i> Show advanced options
<i class="fa fa-plus space-right" aria-hidden="true"></i> <por-translation key="TEMPLATES.SELECTED_TEMPLATE.FORM.SHOW_ADVANCED_OPTIONS"></por-translation>
</a>
<a class="small interactive" ng-if="state.showAdvancedOptions" ng-click="state.showAdvancedOptions = false;">
<i class="fa fa-minus space-right" aria-hidden="true"></i> Hide advanced options
<i class="fa fa-minus space-right" aria-hidden="true"></i> <por-translation key="TEMPLATES.SELECTED_TEMPLATE.FORM.HIDE_ADVANCED_OPTIONS"></por-translation>
</a>
</div>
</div>
@ -84,13 +95,15 @@
<!-- port-mapping -->
<div class="form-group" >
<div class="col-sm-12" style="margin-top: 5px;">
<label class="control-label text-left">Port mapping</label>
<label class="control-label text-left">
<por-translation key="TEMPLATES.SELECTED_TEMPLATE.FORM.ADVANCED_OPTIONS.PORT_MAPPING.LABEL"></por-translation>
</label>
<span class="label label-default interactive" style="margin-left: 10px;" ng-click="addPortBinding()">
<i class="fa fa-plus-circle" aria-hidden="true"></i> map additional port
<i class="fa fa-plus-circle" aria-hidden="true"></i> <por-translation key="TEMPLATES.SELECTED_TEMPLATE.FORM.ADVANCED_OPTIONS.PORT_MAPPING.MAP_PORT"></por-translation>
</span>
</div>
<div class="col-sm-12" style="margin-top: 10px" ng-if="state.selectedTemplate.Ports.length > 0">
<span class="small text-muted">Portainer will automatically assign a port if you leave the host port empty.</span>
<span class="small text-muted"><por-translation key="TEMPLATES.SELECTED_TEMPLATE.FORM.ADVANCED_OPTIONS.PORT_MAPPING.NOTE"></por-translation></span>
</div>
<!-- !port-mapping -->
<!-- port-mapping-input-list -->
@ -99,7 +112,7 @@
<div ng-repeat="portBinding in state.selectedTemplate.Ports" style="margin-top: 2px;">
<!-- host-port -->
<div class="input-group col-sm-4 input-group-sm">
<span class="input-group-addon">host</span>
<span class="input-group-addon"><por-translation key="COMMON.DOCKER.HOST"></por-translation></span>
<input type="text" class="form-control" ng-model="portBinding.hostPort" placeholder="e.g. 80 or 1.2.3.4:80 (optional)">
</div>
<!-- !host-port -->
@ -108,7 +121,7 @@
</span>
<!-- container-port -->
<div class="input-group col-sm-4 input-group-sm">
<span class="input-group-addon">container</span>
<span class="input-group-addon"><por-translation key="COMMON.DOCKER.CONTAINER"></por-translation></span>
<input type="text" class="form-control" ng-model="portBinding.containerPort" placeholder="e.g. 80">
</div>
<!-- !container-port -->
@ -131,13 +144,15 @@
<!-- volume-mapping -->
<div class="form-group" >
<div class="col-sm-12" style="margin-top: 5px;">
<label class="control-label text-left">Volume mapping</label>
<label class="control-label text-left">
<por-translation key="TEMPLATES.SELECTED_TEMPLATE.FORM.ADVANCED_OPTIONS.VOLUME_MAPPING.LABEL"></por-translation>
</label>
<span class="label label-default interactive" style="margin-left: 10px;" ng-click="addVolume()">
<i class="fa fa-plus-circle" aria-hidden="true"></i> map additional volume
<i class="fa fa-plus-circle" aria-hidden="true"></i> <por-translation key="TEMPLATES.SELECTED_TEMPLATE.FORM.ADVANCED_OPTIONS.VOLUME_MAPPING.MAP_VOLUME"></por-translation>
</span>
</div>
<div class="col-sm-12" style="margin-top: 10px" ng-if="state.selectedTemplate.Volumes.length > 0">
<span class="small text-muted">Portainer will automatically create and map a local volume when using the <b>auto</b> option.</span>
<span class="small text-muted"><por-translation key="TEMPLATES.SELECTED_TEMPLATE.FORM.ADVANCED_OPTIONS.VOLUME_MAPPING.NOTE"></por-translation></span>
</div>
<div ng-repeat="volume in state.selectedTemplate.Volumes">
<div class="col-sm-12" style="margin-top: 10px;">
@ -145,16 +160,16 @@
<div class="col-sm-12 form-inline">
<!-- container-path -->
<div class="input-group input-group-sm col-sm-6">
<span class="input-group-addon">container</span>
<span class="input-group-addon"><por-translation key="COMMON.DOCKER.CONTAINER"></por-translation></span>
<input type="text" class="form-control" ng-model="volume.containerPath" placeholder="e.g. /path/in/container">
</div>
<!-- !container-path -->
<!-- volume-type -->
<div class="input-group col-sm-5" style="margin-left: 5px;">
<div class="btn-group btn-group-sm">
<label class="btn btn-primary" ng-model="volume.type" uib-btn-radio="'auto'" ng-click="volume.name = ''">Auto</label>
<label class="btn btn-primary" ng-model="volume.type" uib-btn-radio="'volume'" ng-click="volume.name = ''">Volume</label>
<label class="btn btn-primary" ng-model="volume.type" uib-btn-radio="'bind'" ng-click="volume.name = ''">Bind</label>
<label class="btn btn-primary" ng-model="volume.type" uib-btn-radio="'auto'" ng-click="volume.name = ''"><por-translation key="TEMPLATES.SELECTED_TEMPLATE.FORM.ADVANCED_OPTIONS.VOLUME_MAPPING.TYPE.AUTO"></por-translation></label>
<label class="btn btn-primary" ng-model="volume.type" uib-btn-radio="'volume'" ng-click="volume.name = ''"><por-translation key="TEMPLATES.SELECTED_TEMPLATE.FORM.ADVANCED_OPTIONS.VOLUME_MAPPING.TYPE.VOLUME"></por-translation></label>
<label class="btn btn-primary" ng-model="volume.type" uib-btn-radio="'bind'" ng-click="volume.name = ''"><por-translation key="TEMPLATES.SELECTED_TEMPLATE.FORM.ADVANCED_OPTIONS.VOLUME_MAPPING.TYPE.BIND"></por-translation></label>
</div>
<button class="btn btn-sm btn-danger" type="button" ng-click="removeVolume($index)">
<i class="fa fa-trash" aria-hidden="true"></i>
@ -168,24 +183,24 @@
<i class="fa fa-long-arrow-right" aria-hidden="true"></i>
<!-- volume -->
<div class="input-group input-group-sm col-sm-6" ng-if="volume.type === 'volume'">
<span class="input-group-addon">volume</span>
<span class="input-group-addon"><por-translation key="COMMON.DOCKER.VOLUME"></por-translation></span>
<select class="form-control" ng-model="volume.name">
<option selected disabled hidden value="">Select a volume</option>
<option selected disabled hidden value="" translate>TEMPLATES.SELECTED_TEMPLATE.FORM.ADVANCED_OPTIONS.VOLUME_MAPPING.SELECT_VOLUME</option>
<option ng-repeat="vol in availableVolumes" ng-value="vol.Name">{{ vol.Name|truncate:30}}</option>
</select>
</div>
<!-- !volume -->
<!-- bind -->
<div class="input-group input-group-sm col-sm-6" ng-if="volume.type === 'bind'">
<span class="input-group-addon">host</span>
<span class="input-group-addon"><por-translation key="COMMON.DOCKER.HOST"></por-translation></span>
<input type="text" class="form-control" ng-model="volume.name" placeholder="e.g. /path/on/host">
</div>
<!-- !bind -->
<!-- read-only -->
<div class="input-group input-group-sm col-sm-5" style="margin-left: 5px;">
<div class="btn-group btn-group-sm">
<label class="btn btn-primary" ng-model="volume.readOnly" uib-btn-radio="false">Writable</label>
<label class="btn btn-primary" ng-model="volume.readOnly" uib-btn-radio="true">Read-only</label>
<label class="btn btn-primary" ng-model="volume.readOnly" uib-btn-radio="false"><por-translation key="TEMPLATES.SELECTED_TEMPLATE.FORM.ADVANCED_OPTIONS.VOLUME_MAPPING.WRITABLE"></por-translation></label>
<label class="btn btn-primary" ng-model="volume.readOnly" uib-btn-radio="true"><por-translation key="TEMPLATES.SELECTED_TEMPLATE.FORM.ADVANCED_OPTIONS.VOLUME_MAPPING.READONLY"></por-translation></label>
</div>
</div>
<!-- !read-only -->
@ -200,14 +215,16 @@
<!-- actions -->
<div class="form-group">
<div class="col-sm-12">
<button type="button" class="btn btn-primary btn-sm" ng-disabled="!formValues.network" ng-click="createTemplate()">Create</button>
<button type="button" class="btn btn-primary btn-sm" ng-disabled="!formValues.network" ng-click="createTemplate()"><por-translation key="COMMON.VERBS.CREATE"></por-translation></button>
<i id="createContainerSpinner" class="fa fa-cog fa-spin" style="margin-left: 5px; display: none;"></i>
<span class="small text-muted" style="margin-left: 10px" ng-if="globalNetworkCount === 0 && applicationState.endpoint.mode.provider === 'DOCKER_SWARM' && !state.formValidationError">
When using Swarm, we recommend deploying containers in a shared network. Looks like you don't have any shared network, head over the <a ui-sref="networks">networks view</a> to create one.
<span class="small text-muted" style="margin-left: 10px" ng-if="true">
<por-translation key="TEMPLATES.SELECTED_TEMPLATE.FORM.ACTIONS.SWARM_NOTE_NETWORK" compile="true"></por-translation>
</span>
<span ng-if="applicationState.endpoint.mode.provider === 'DOCKER_SWARM_MODE' && !state.formValidationError" style="margin-left: 10px">
<i class="fa fa-exclamation-triangle" aria-hidden="true"></i>
<span class="small text-muted" style="margin-left: 5px;">App templates cannot be deployed as Swarm Mode services for the moment. You can still use them to quickly deploy containers on the Docker host.</span>
<span class="small text-muted" style="margin-left: 5px;">
<por-translation key="TEMPLATES.SELECTED_TEMPLATE.FORM.ACTIONS.SWARM_NOTE_STACK"></por-translation>
</span>
</span>
<span class="text-danger" ng-if="state.formValidationError" style="margin-left: 5px;">{{ state.formValidationError }}</span>
</div>
@ -223,9 +240,9 @@
<rd-template-widget>
<rd-widget-header icon="fa-rocket" title="Templates">
<div ng-if="availableCategories.length > 0" class="pull-right">
Category
<por-translation key="TEMPLATES.WIDGET_TEMPLATE_LIST.HEADER.CATEGORY"></por-translation>
<select ng-model="state.filters.Categories">
<option value="!">All</option>
<option value="!" translate>COMMON.UI.ALL</option>
<option ng-repeat="category in availableCategories" value="{{ category }}">{{ category }}</option>
</select>
</div>
@ -235,15 +252,15 @@
<!-- Platform -->
<span class="btn-group btn-group-sm" style="margin-right: 15px;">
<label class="btn btn-primary" ng-model="state.filters.Platform" uib-btn-radio="'!'">
All
<por-translation key="COMMON.UI.ALL"></por-translation>
</label>
<label class="btn btn-primary" ng-model="state.filters.Platform" uib-btn-radio="'windows'">
<i class="fa fa-windows" aria-hidden="true"></i>
Windows
<por-translation key="TEMPLATES.WIDGET_TEMPLATE_LIST.HEADER.PLATFORM_FILTERS.WINDOWS"></por-translation>
</label>
<label class="btn btn-primary" ng-model="state.filters.Platform" uib-btn-radio="'linux'">
<i class="fa fa-linux" aria-hidden="true"></i>
Linux
<por-translation key="TEMPLATES.WIDGET_TEMPLATE_LIST.HEADER.PLATFORM_FILTERS.LINUX"></por-translation>
</label>
</span>
</div>
@ -288,10 +305,10 @@
<!-- !template -->
</div>
<div ng-if="!templates" class="text-center text-muted">
Loading...
<por-translation key="COMMON.UI.LOADING"></por-translation>
</div>
<div ng-if="(templates | filter:state.filters:true).length == 0" class="text-center text-muted">
No templates available.
<por-translation key="TEMPLATES.WIDGET_TEMPLATE_LIST.LIST.EMPTY"></por-translation>
</div>
</div>
</rd-widget-body>

@ -1,6 +1,7 @@
angular.module('portainer').component('porTranslation', {
bindings: {
'key': '@'
'key': '@',
'compile': '@'
},
template: '<span translate>{{ $ctrl.key }}</span>'
template: '<span translate translate-compile="{{ $ctrl.compile ? $ctrl.compile : false }}">{{ $ctrl.key }}</span>'
});

@ -1,4 +1,20 @@
{
"COMMON": {
"VERBS": {
"CREATE": "Create",
"REFRESH": "Refresh",
"HIDE": "Hide"
},
"DOCKER": {
"CONTAINER": "container",
"VOLUME": "volume",
"HOST": "host",
},
"UI": {
"LOADING": "Loading...",
"ALL": "All"
}
},
"WIDGETS": {
"HEADER_CONTENT": {
"USER_PREFERENCES": "my account",
@ -37,6 +53,60 @@
}
}
},
"TEMPLATES": {
"HEADER": {
"TITLE": "Application templates list",
"CONTENT": "Templates"
},
"SELECTED_TEMPLATE": {
"TITLE_INFORMATION": "Information",
"TITLE_CONFIGURATION": "Configuration",
"FORM": {
"NAME": "Name",
"NETWORK": "Network",
"SELECT_CONTAINER": "Select a container",
"SHOW_ADVANCED_OPTIONS": "Show advanced options",
"HIDE_ADVANCED_OPTIONS": "Hide advanced options",
"ADVANCED_OPTIONS": {
"PORT_MAPPING": {
"LABEL": "Port mapping",
"MAP_PORT": "map additional port",
"NOTE": "Portainer will automatically assign a port if you leave the host port empty.",
"HOST": "host"
},
"VOLUME_MAPPING": {
"LABEL": "Volume mapping",
"MAP_VOLUME": "map additional volume",
"NOTE": "Portainer will automatically create and map a local volume when using the <b>auto</b> option.",
"TYPE": {
"AUTO": "Auto",
"VOLUME": "Volume",
"BIND": "Bind"
},
"SELECT_VOLUME": "Select a volume",
"WRITABLE": "Writable",
"READONLY": "Read-only"
}
},
"ACTIONS": {
"SWARM_NOTE_NETWORK": "When using Swarm, we recommend deploying containers in a shared network. Looks like you don't have any shared network, head over the <a ui-sref='networks'>networks view</a> to create one.",
"SWARM_NOTE_STACK": "App templates cannot be deployed as Swarm Mode services for the moment. You can still use them to quickly deploy containers on the Docker host."
}
}
},
"WIDGET_TEMPLATE_LIST": {
"HEADER": {
"CATEGORY": "Category",
"PLATFORM_FILTERS": {
"WINDOWS": "Windows",
"LINUX": "Linux"
}
},
"LIST": {
"EMPTY": "No templates available."
}
}
},
"DASHBOARD": {
"HEADER": {
"TITLE": "Home",

@ -1,4 +1,20 @@
{
"COMMON": {
"VERBS": {
"CREATE": "Créer",
"REFRESH": "Rafraîchir",
"HIDE": "Cacher"
},
"DOCKER": {
"CONTAINER": "conteneur",
"VOLUME": "volume",
"HOST": "hôte"
},
"UI": {
"LOADING": "Chargement...",
"ALL": "Tous"
}
},
"WIDGETS": {
"HEADER_CONTENT": {
"USER_PREFERENCES": "mon compte",
@ -37,6 +53,59 @@
}
}
},
"TEMPLATES": {
"HEADER": {
"TITLE": "Liste de templates applicatifs",
"CONTENT": "Templates"
},
"SELECTED_TEMPLATE": {
"TITLE_INFORMATION": "Information",
"TITLE_CONFIGURATION": "Configuration",
"FORM": {
"NAME": "Nom",
"NETWORK": "Réseau",
"SELECT_CONTAINER": "Choisir un conteneur",
"SHOW_ADVANCED_OPTIONS": "Afficher les options avancées",
"HIDE_ADVANCED_OPTIONS": "Cacher les options avancées",
"ADVANCED_OPTIONS": {
"PORT_MAPPING": {
"LABEL": "Associer port",
"MAP_PORT": "associer un port supplémentaire",
"NOTE": "Portainer va automatiquement assigner un port quand le port hôte est vide."
},
"VOLUME_MAPPING": {
"LABEL": "Associer volume",
"MAP_VOLUME": "associer un volume supplémentaire",
"NOTE": "Portainer va automatiquement créer et associer un volume local quand l'option <b>auto</b> est sélectionnée.",
"TYPE": {
"AUTO": "Auto",
"VOLUME": "Volume",
"BIND": "Bind"
},
"SELECT_VOLUME": "Choisir un volume",
"WRITABLE": "Ecriture",
"READONLY": "Lecture seule"
}
},
"ACTIONS": {
"SWARM_NOTE_NETWORK": "Vous utilisez Swarm, nous recommandons le deployment de vos conteneurs dans un réseau partagé. Vous pouvez en créer un dans la <a ui-sref='networks'>vue réseaux</a>.",
"SWARM_NOTE_STACK": "Les App Templates ne peuvent pas être déployés en tant que services Swarm pour le moment. Vous pouvez toujours les utiliser pour déployer des conteneurs sur cet hôte."
}
}
},
"WIDGET_TEMPLATE_LIST": {
"HEADER": {
"CATEGORY": "Catégorie",
"PLATFORM_FILTERS": {
"WINDOWS": "Windows",
"LINUX": "Linux"
}
},
"LIST": {
"EMPTY": "Aucun template disponible."
}
}
},
"DASHBOARD": {
"HEADER": {
"TITLE": "Accueil",

Loading…
Cancel
Save