Skip to content

Commit 9dc24a4

Browse files
committed
FEATURE: Show language switcher for anon users
1 parent 620d774 commit 9dc24a4

File tree

7 files changed

+107
-24
lines changed

7 files changed

+107
-24
lines changed

app/services/discourse_translator/base.rb

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,9 @@ def self.strip_tags_for_detection(detection_text)
7979
end
8080

8181
def self.text_for_detection(topic_or_post)
82-
strip_tags_for_detection(
83-
get_text(topic_or_post).truncate(DETECTION_CHAR_LIMIT, omission: nil),
82+
strip_tags_for_detection(get_text(topic_or_post)).truncate(
83+
DETECTION_CHAR_LIMIT,
84+
omission: nil,
8485
)
8586
end
8687

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# frozen_string_literal: true
2+
3+
class LanguageSwitcherSettingValidator
4+
def initialize(opts = {})
5+
@opts = opts
6+
end
7+
8+
def valid_value?(val)
9+
return true if val == "f"
10+
SiteSetting.set_locale_from_cookie
11+
end
12+
13+
def error_message
14+
I18n.t("site_settings.errors.set_locale_cookie_requirements")
15+
end
16+
end
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import Component from "@glimmer/component";
2+
import {fn} from "@ember/helper";
3+
import {action} from "@ember/object";
4+
import {service} from "@ember/service";
5+
import DButton from "discourse/components/d-button";
6+
import DropdownMenu from "discourse/components/dropdown-menu";
7+
import cookie from "discourse/lib/cookie";
8+
import DMenu from "float-kit/components/d-menu";
9+
10+
export default class LanguageSwitcher extends Component {
11+
@service site;
12+
@service siteSettings;
13+
@service router;
14+
15+
get localeOptions() {
16+
return JSON.parse(this.siteSettings.available_locales).map(({ name, value }) => {
17+
return {
18+
label: name,
19+
value,
20+
};
21+
});
22+
}
23+
24+
@action
25+
async changeLocale(locale) {
26+
cookie("locale", locale);
27+
this.dMenu.close();
28+
// we need a hard refresh here for the locale to take effect
29+
window.location.reload();
30+
}
31+
32+
@action
33+
onRegisterApi(api) {
34+
this.dMenu = api;
35+
}
36+
37+
<template>
38+
<DMenu
39+
title="Language switcher"
40+
@icon="language"
41+
class="btn-flat btn-icon icon"
42+
@onRegisterApi={{this.onRegisterApi}}
43+
>
44+
<:content>
45+
<DropdownMenu as |dropdown|>
46+
{{#each this.localeOptions as |option|}}
47+
<dropdown.item
48+
class="discourse-translator_locale-option"
49+
data-menu-option-id={{option.value}}
50+
>
51+
<DButton
52+
@translatedLabel={{option.label}}
53+
@action={{fn this.changeLocale option.value}}
54+
/>
55+
</dropdown.item>
56+
{{/each}}
57+
</DropdownMenu>
58+
</:content>
59+
</DMenu>
60+
</template>
61+
}

assets/javascripts/discourse/initializers/extend-for-translate-button.js

Lines changed: 15 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,31 @@
11
import { ajax } from "discourse/lib/ajax";
22
import { popupAjaxError } from "discourse/lib/ajax-error";
3+
import { withSilencedDeprecations } from "discourse/lib/deprecated";
34
import { withPluginApi } from "discourse/lib/plugin-api";
4-
import { withSilencedDeprecations } from "discourse-common/lib/deprecated";
55
import { i18n } from "discourse-i18n";
6+
import LanguageSwitcher from "../components/language-switcher";
67
import ToggleTranslationButton from "../components/post-menu/toggle-translation-button";
78
import TranslatedPost from "../components/translated-post";
89

910
function initializeTranslation(api) {
1011
const siteSettings = api.container.lookup("service:site-settings");
12+
if (!siteSettings.translator_enabled) {
13+
return;
14+
}
15+
1116
const currentUser = api.getCurrentUser();
1217

13-
if (!currentUser || !siteSettings.translator_enabled) {
14-
return;
18+
if (!currentUser && siteSettings.experimental_anon_language_switcher) {
19+
api.headerIcons.add(
20+
"discourse-translator_language-switcher",
21+
LanguageSwitcher,
22+
{ before: ["search"] }
23+
);
1524
}
1625

17-
customizePostMenu(api);
26+
if (currentUser) {
27+
customizePostMenu(api);
28+
}
1829
}
1930

2031
function customizePostMenu(api, container) {
@@ -123,24 +134,6 @@ function customizeWidgetPostMenu(api) {
123134
post.set("translated_text", "");
124135
}
125136
});
126-
127-
api.addPostMenuButton("translate", (attrs, state) => {
128-
if (!attrs.can_translate) {
129-
return;
130-
}
131-
132-
const [action, title] = !state.isTranslated
133-
? ["translate", "translator.view_translation"]
134-
: ["hideTranslation", "translator.hide_translation"];
135-
136-
return {
137-
action,
138-
title,
139-
icon: "globe",
140-
position: "first",
141-
className: state.isTranslated ? "translated" : null,
142-
};
143-
});
144137
}
145138

146139
export default {

config/locales/server.en.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ en:
1717
translator_azure_custom_subdomain: "Required if using a Virtual Network or Firewall for Azure Cognitive Services. Note: Only enter the custom subdomain not the full custom endpoint."
1818
restrict_translation_by_group: "Only allowed groups can translate"
1919
restrict_translation_by_poster_group: "Only allow translation of posts made by users in allowed groups. If empty, allow translations of posts from all users."
20+
experimental_anon_language_switcher: "Enable experimental language switcher for anonymous users. This will allow anonymous users to switch between translated versions of Discourse and user-contributed content in topics."
21+
errors:
22+
set_locale_cookie_requirements: "The experimental language switcher for anonymous users requires the `set locale from cookie` site setting to be enabled."
2023
translator:
2124
failed: "The translator is unable to translate this content (%{source_locale}) to the default language of this site (%{target_locale})."
2225
not_supported: "This language is not supported by the translator."

config/settings.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,3 +102,7 @@ discourse_translator:
102102
default: ""
103103
client: true
104104
type: group_list
105+
experimental_anon_language_switcher:
106+
default: false
107+
client: true
108+
validator: "LanguageSwitcherSettingValidator"

spec/services/base_spec.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,11 @@ class EmptyTranslator < DiscourseTranslator::Base
8282
post.cooked = text
8383
expect(DiscourseTranslator::Base.text_for_detection(post)).to eq(text)
8484
end
85+
86+
it "strips text before truncation" do
87+
post.cooked = "<img src='http://example.com/image.png' />" + "a" * 1000
88+
expect(DiscourseTranslator::Base.text_for_detection(post)).to eq("a" * 1000)
89+
end
8590
end
8691

8792
describe ".text_for_translation" do

0 commit comments

Comments
 (0)