UX: Text customization for different languages. (#11729)
Admins can now edit translations in different languages without having to change their locale. We display a warning when there's a fallback language set.
This commit is contained in:
@@ -7,6 +7,7 @@ import { popupAjaxError } from "discourse/lib/ajax-error";
|
||||
|
||||
export default Controller.extend(bufferedProperty("siteText"), {
|
||||
saved: false,
|
||||
queryParams: ["locale"],
|
||||
|
||||
@discourseComputed("buffered.value")
|
||||
saveDisabled(value) {
|
||||
@@ -15,9 +16,11 @@ export default Controller.extend(bufferedProperty("siteText"), {
|
||||
|
||||
actions: {
|
||||
saveChanges() {
|
||||
const buffered = this.buffered;
|
||||
const attrs = this.buffered.getProperties("value");
|
||||
attrs.locale = this.locale;
|
||||
|
||||
this.siteText
|
||||
.save(buffered.getProperties("value"))
|
||||
.save(attrs)
|
||||
.then(() => {
|
||||
this.commitBuffer();
|
||||
this.set("saved", true);
|
||||
@@ -27,10 +30,11 @@ export default Controller.extend(bufferedProperty("siteText"), {
|
||||
|
||||
revertChanges() {
|
||||
this.set("saved", false);
|
||||
|
||||
bootbox.confirm(I18n.t("admin.site_text.revert_confirm"), (result) => {
|
||||
if (result) {
|
||||
this.siteText
|
||||
.revert()
|
||||
.revert(this.locale)
|
||||
.then((props) => {
|
||||
const buffered = this.buffered;
|
||||
buffered.setProperties(props);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import Controller from "@ember/controller";
|
||||
import discourseComputed from "discourse-common/utils/decorators";
|
||||
import discourseDebounce from "discourse-common/lib/debounce";
|
||||
let lastSearch;
|
||||
|
||||
@@ -6,23 +7,49 @@ export default Controller.extend({
|
||||
searching: false,
|
||||
siteTexts: null,
|
||||
preferred: false,
|
||||
queryParams: ["q", "overridden"],
|
||||
queryParams: ["q", "overridden", "locale"],
|
||||
locale: null,
|
||||
|
||||
q: null,
|
||||
overridden: false,
|
||||
|
||||
init() {
|
||||
this._super(...arguments);
|
||||
|
||||
this.set("locale", this.siteSettings.default_locale);
|
||||
},
|
||||
|
||||
_performSearch() {
|
||||
this.store
|
||||
.find("site-text", this.getProperties("q", "overridden"))
|
||||
.find("site-text", this.getProperties("q", "overridden", "locale"))
|
||||
.then((results) => {
|
||||
this.set("siteTexts", results);
|
||||
})
|
||||
.finally(() => this.set("searching", false));
|
||||
},
|
||||
|
||||
@discourseComputed()
|
||||
availableLocales() {
|
||||
return JSON.parse(this.siteSettings.available_locales);
|
||||
},
|
||||
|
||||
@discourseComputed("locale")
|
||||
fallbackLocaleFullName() {
|
||||
if (this.siteTexts.extras.fallback_locale) {
|
||||
return this.availableLocales.find((l) => {
|
||||
return l.value === this.siteTexts.extras.fallback_locale;
|
||||
}).name;
|
||||
}
|
||||
},
|
||||
|
||||
actions: {
|
||||
edit(siteText) {
|
||||
this.transitionToRoute("adminSiteText.edit", siteText.get("id"));
|
||||
this.transitionToRoute("adminSiteText.edit", siteText.get("id"), {
|
||||
queryParams: {
|
||||
locale: this.locale,
|
||||
localeFullName: this.availableLocales[this.locale],
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
toggleOverridden() {
|
||||
@@ -39,5 +66,14 @@ export default Controller.extend({
|
||||
lastSearch = q;
|
||||
}
|
||||
},
|
||||
|
||||
updateLocale(value) {
|
||||
this.setProperties({
|
||||
searching: true,
|
||||
locale: value,
|
||||
});
|
||||
|
||||
discourseDebounce(this, this._performSearch, 400);
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import RestModel from "discourse/models/rest";
|
||||
import { ajax } from "discourse/lib/ajax";
|
||||
const { getProperties } = Ember;
|
||||
import { getProperties } from "@ember/object";
|
||||
|
||||
export default RestModel.extend({
|
||||
revert() {
|
||||
return ajax(`/admin/customize/site_texts/${this.id}`, {
|
||||
revert(locale) {
|
||||
return ajax(`/admin/customize/site_texts/${this.id}?locale=${locale}`, {
|
||||
type: "DELETE",
|
||||
}).then((result) => getProperties(result.site_text, "value", "can_revert"));
|
||||
},
|
||||
|
||||
@@ -1,10 +1,30 @@
|
||||
import Route from "@ember/routing/route";
|
||||
import { ajax } from "discourse/lib/ajax";
|
||||
|
||||
export default Route.extend({
|
||||
queryParams: {
|
||||
locale: { replace: true },
|
||||
},
|
||||
|
||||
model(params) {
|
||||
return this.store.find("site-text", params.id);
|
||||
return ajax(
|
||||
`/admin/customize/site_texts/${params.id}?locale=${params.locale}`
|
||||
).then((result) => {
|
||||
return this.store.createRecord("site-text", result.site_text);
|
||||
});
|
||||
},
|
||||
|
||||
setupController(controller, siteText) {
|
||||
controller.setProperties({ siteText, saved: false });
|
||||
const locales = JSON.parse(this.siteSettings.available_locales);
|
||||
|
||||
const localeFullName = locales.find((locale) => {
|
||||
return locale.value === controller.locale;
|
||||
}).name;
|
||||
|
||||
controller.setProperties({
|
||||
siteText,
|
||||
saved: false,
|
||||
localeFullName: localeFullName,
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
@@ -6,12 +6,13 @@ export default Route.extend({
|
||||
queryParams: {
|
||||
q: { replace: true },
|
||||
overridden: { replace: true },
|
||||
locale: { replace: true },
|
||||
},
|
||||
|
||||
model(params) {
|
||||
return this.store.find(
|
||||
"site-text",
|
||||
getProperties(params, "q", "overridden")
|
||||
getProperties(params, "q", "overridden", "locale")
|
||||
);
|
||||
},
|
||||
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
<div class="edit-site-text">
|
||||
|
||||
<div class="title">
|
||||
<h3>{{siteText.id}}</h3>
|
||||
</div>
|
||||
|
||||
<div class="title">
|
||||
<h4>{{i18n "admin.site_text.locale"}} {{localeFullName}}</h4>
|
||||
</div>
|
||||
|
||||
{{expanding-text-area value=buffered.value rows="1" class="site-text-value"}}
|
||||
|
||||
{{#save-controls model=siteText action=(action "saveChanges") saved=saved saveDisabled=saveDisabled}}
|
||||
@@ -12,7 +15,7 @@
|
||||
{{/if}}
|
||||
{{/save-controls}}
|
||||
|
||||
{{#link-to "adminSiteText.index" class="go-back"}}
|
||||
{{#link-to "adminSiteText.index" (query-params locale=locale) class="go-back"}}
|
||||
{{d-icon "arrow-left"}}
|
||||
{{i18n "admin.site_text.go_back"}}
|
||||
{{/link-to}}
|
||||
|
||||
@@ -16,6 +16,21 @@
|
||||
</div>
|
||||
|
||||
<p class="filter-options">
|
||||
<div class="locale">
|
||||
<label>{{i18n "admin.site_text.locale"}}</label>
|
||||
{{combo-box
|
||||
valueProperty="value"
|
||||
content=availableLocales
|
||||
value=locale
|
||||
onChange=(action "updateLocale")
|
||||
class="locale-search"
|
||||
options=(hash
|
||||
filterable=true
|
||||
none="user.locale.default"
|
||||
)
|
||||
}}
|
||||
</div>
|
||||
|
||||
<label>
|
||||
{{input type="checkbox" checked=overridden click=(action "toggleOverridden")}}
|
||||
{{i18n "admin.site_text.show_overriden"}}
|
||||
@@ -24,6 +39,13 @@
|
||||
</div>
|
||||
|
||||
{{#conditional-loading-spinner condition=searching}}
|
||||
{{#if fallbackLocaleFullName}}
|
||||
<div class="alert alert-info">
|
||||
{{d-icon "exclamation-circle"}}
|
||||
{{i18n "admin.site_text.fallback_locale_warning" fallback=fallbackLocaleFullName}}
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
{{#if siteTexts.extras.recommended}}
|
||||
<p><b>{{i18n "admin.site_text.recommended"}}</b></p>
|
||||
{{/if}}
|
||||
|
||||
Reference in New Issue
Block a user