Skip to content

Commit

Permalink
Merge pull request #1082 from didoda/feat/language-selector
Browse files Browse the repository at this point in the history
Language selection with autocomplete dropdown
  • Loading branch information
didoda authored Feb 21, 2024
2 parents 3ac4a9b + 547df54 commit 5a65921
Show file tree
Hide file tree
Showing 7 changed files with 143 additions and 41 deletions.
1 change: 1 addition & 0 deletions resources/js/app/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ const _vueInstance = new Vue({
ShowHide:() => import(/* webpackChunkName: "show-hide" */'app/components/show-hide/show-hide'),
SystemInfo:() => import(/* webpackChunkName: "system-info" */'app/components/system-info/system-info'),
UserAccesses:() => import(/* webpackChunkName: "user-accesses" */'app/components/user-accesses/user-accesses'),
LanguageSelector:() => import(/* webpackChunkName: "language-selector" */'app/components/language-selector/language-selector'),
AppIcon,
},

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
<template>
<div class="languageSelector">
<div class="input select">
<label for="lang">{{ title }}</label>
<Treeselect
v-if="readonly === 0"
placeholder
:form="form"
:options="languagesOptions"
:disable-branch-nodes="true"
:multiple="false"
v-model="lang"
@input="onChange"
/>
<select v-else><option>{{ languages[lang] }}</option></select>
<input v-if="reference" type="hidden" :id="reference" :value="lang" />
<input v-if="reference" type="hidden" :id="`${reference}Label`" :value="languages[lang]" />
<input v-if="reference != 'translateFrom'" type="hidden" name="lang" v-model="lang" />
</div>
</div>
</template>
<script>
import { Treeselect } from '@riophae/vue-treeselect'
import '@riophae/vue-treeselect/dist/vue-treeselect.css'
import { t } from 'ttag';
export default {
name: 'LanguageSelector',
components: {
Treeselect,
},
props: {
excludeLang: {
type: String,
default: '',
},
language: {
type: String,
default: '',
},
languageLabel: {
type: String,
default: '',
},
languages: {
type: Object,
default: () => {},
},
readonly: {
type: Number,
default: 0,
},
reference: {
type: String,
default: '',
},
},
data() {
return {
form: 'langSelector',
lang: '',
languagesOptions: [],
title: '',
msgMainLanguage: t`The main language is`,
};
},
mounted() {
this.$nextTick(() => {
this.lang = this.language == '' ? null : this.language;
this.title = this.languageLabel || this.msgMainLanguage;
this.languages['null'] = '';
if (this.excludeLang) {
delete this.languages[this.excludeLang];
}
this.languagesOptions = Object.keys(this.languages).map((key) => {
return {
id: key,
label: this.languages[key],
};
});
});
},
methods: {
onChange() {
this.$emit('change', this.lang);
}
},
};
</script>
<style>
.languageSelector {
max-width: 150px;
}
.languageSelector span.main {
font-weight: bold;
}
</style>
1 change: 1 addition & 0 deletions resources/js/app/components/property-view/property-view.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ export default {
Permission:() => import(/* webpackChunkName: "permission" */'app/components/permission/permission'),
Permissions:() => import(/* webpackChunkName: "permissions" */'app/components/permissions/permissions'),
PermissionToggle: () => import(/* webpackChunkName: "permission-toggle" */'app/components/permission-toggle/permission-toggle'),
LanguageSelector:() => import(/* webpackChunkName: "language-selector" */'app/components/language-selector/language-selector'),
},

props: {
Expand Down
7 changes: 4 additions & 3 deletions resources/js/app/pages/modules/view.vue
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export default {
ObjectTypesList: () => import(/* webpackChunkName: "object-types-list" */'app/components/object-types-list/object-types-list'),
KeyValueList: () => import(/* webpackChunkName: "key-value-list" */'app/components/json-fields/key-value-list'),
StringList: () => import(/* webpackChunkName: "string-list" */'app/components/json-fields/string-list'),
LanguageSelector:() => import(/* webpackChunkName: "language-selector" */'app/components/language-selector/language-selector'),
},
props: {
Expand Down Expand Up @@ -226,10 +227,10 @@ export default {
}
if (!object.to) {
// use `value` from select on new translations
object.to = this.$refs.translateTo.value;
object.to = document.getElementById('translateTo').value;
}
object.fromLabel = this.$refs.translateFrom.options[this.$refs.translateFrom.selectedIndex].text || '???';
object.toLabel = this.$refs.translateTo.options[this.$refs.translateTo.selectedIndex].text || '???';
object.fromLabel = document.getElementById('translateFromLabel').value;
object.toLabel = document.getElementById('translateToLabel').value;
const translator = document.getElementById('translatorEngine').value;
Expand Down
8 changes: 5 additions & 3 deletions templates/Element/Form/related_translations.twig
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,12 @@
<div v-show="isOpen" class="tab-container">

<div>
{% set lang = object.id ? object.attributes.lang : config('Project.config.I18n.default') %}
{{ Property.control('lang', lang, { 'label': __('The main language is') })|raw }}
<language-selector
language="{{ object.id ? object.attributes.lang : config('Project.config.I18n.default') }}"
:languages="{{ config('Project.config.I18n.languages')|default([])|json_encode|escape('html_attr') }}">
</language-selector>

{% if translatable %}
{% if translatable and object.attributes.lang %}
{{ Html.link(__('Add translation'), {
'_name': 'translations:add',
'object_type': object.type,
Expand Down
68 changes: 34 additions & 34 deletions templates/Element/translation.twig
Original file line number Diff line number Diff line change
Expand Up @@ -14,29 +14,25 @@
<div class="row">
<div class="column">
<div class="lang-header is-flex align-center">
{% set languageLabel = "#{__('Language')}" %}
{% set options = Schema.controlOptions('lang', null, [])|default({})|merge({
'label': languageLabel,
'value': translation.attributes.lang|default(newLang),
}) %}
{% if options.options %}
{% set langOptions = options.options|filter((v, k) => v.value != object.attributes.lang) %}
{% set options = options|merge({
'options': langOptions,
'ref': 'translateTo',
}) %}
{% endif %}
{% if translation.attributes.lang %}
{% set options = options|merge({'readonly': true}) %}
{% endif %}
{{ Form.control('lang', options)|raw }}
<language-selector
exclude-lang="{{ object.attributes.lang }}"
language="{{ translation.attributes.lang ? translation.attributes.lang : newLang }}"
:languages="{{ config('Project.config.I18n.languages')|default([])|json_encode|escape('html_attr') }}"
language-label="{{ __('Language') }}"
:readonly={{ translation.attributes.lang ? 1 : 0 }}
reference="translateTo">
</language-selector>
{% if config('Translators') %}
<label>{{ __('Translator Engine') }}</label>
<select id="translatorEngine">
{% for key,translator in config('Translators') %}
<option value="{{ key }}">{{ translator.name }}</option>
{% endfor %}
</select>
<div>
<div class="input select">
<label>{{ __('Translator Engine') }}</label>
<select id="translatorEngine">
{% for key,translator in config('Translators') %}
<option value="{{ key }}">{{ translator.name }}</option>
{% endfor %}
</select>
</div>
</div>
{% set data = [] %}
{% for key in translatable %}
{% set data = data|merge({
Expand All @@ -48,23 +44,27 @@
}
}) %}
{% endfor %}
<a class="button has-background-module-translations" @click.prevent="translateAll({{ data|json_encode }}, $event)">
<app-icon icon="carbon:translate"></app-icon>
<span class="ml-05 has-text-size-smallest">{{ __('Auto-translate all fields') }}</span>
</a>
<div>
<div class="input">
<label>{{ __('Auto-translate all fields') }}</label>
<a class="button has-background-module-translations" @click.prevent="translateAll({{ data|json_encode }}, $event)">
<app-icon icon="carbon:translate"></app-icon>
<span class="ml-05 has-text-size-smallest">{{ __('Auto-translate') }}</span>
</a>
</div>
</div>
{% endif %}
</div>
</div>
<div class="column">
<div class="lang-header is-flex align-bottom">
{% set languageLabel = "#{__('Original language')}" %}
{% set options = Schema.controlOptions('lang', null, [])|merge({
'label': languageLabel,
'value': object.attributes.lang,
'disabled' : true,
'ref': 'translateFrom',
}) %}
{{ Form.control('lang', options)|raw }}
<language-selector
language="{{ object.attributes.lang ? object.attributes.lang : config('Project.config.I18n.default')|json_encode }}"
:languages="{{ config('Project.config.I18n.languages')|default([])|json_encode|escape('html_attr') }}"
language-label="{{ __('Original language') }}"
:readonly={{ object.attributes.lang ? 1 : 0 }}
reference="translateFrom">
</language-selector>
<a class="button has-background-module-{{ object.type }}" href="{{ Url.build({'_name': 'modules:view', 'object_type': object.type, 'id': object.id }) }}">
<app-icon icon="carbon:launch"></app-icon>
<span class="ml-05">{{ __('Edit') }}</span>
Expand Down
2 changes: 1 addition & 1 deletion templates/Pages/Translations/index.twig
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{% do _view.assign('title', __('Translations')) %}
{% set languages = config('I18n.languages') %}
{% set languages = config('Project.config.I18n.languages') %}

{{ element('Modules/index_header', { 'meta': meta, 'filter': filter, 'Schema': Schema }) }}

Expand Down

0 comments on commit 5a65921

Please sign in to comment.