Skip to content

Commit 2812d3d

Browse files
committed
Add per-language translation support for custom nav links
1 parent 22a1303 commit 2812d3d

3 files changed

Lines changed: 110 additions & 8 deletions

File tree

javascripts/discourse/initializers/init-nav-bar-additions.js

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,25 @@
11
import { withPluginApi } from "discourse/lib/plugin-api";
2+
import I18n from "I18n";
3+
4+
/**
5+
* Resolve a field value from a nav link, checking for a locale-specific
6+
* translation first. Falls back to the base field value.
7+
*/
8+
function getLocalizedField(link, fieldName) {
9+
const translations = link.translations;
10+
if (!translations || translations.length === 0) {
11+
return link[fieldName];
12+
}
13+
14+
const locale = I18n.currentLocale();
15+
16+
// Try exact match first (e.g. "pt_BR"), then prefix match (e.g. "pt")
17+
const match =
18+
translations.find((t) => t.locale === locale) ||
19+
translations.find((t) => locale.startsWith(t.locale));
20+
21+
return (match && match[fieldName]) || link[fieldName];
22+
}
223

324
// Built-in Discourse filter routes that have associated topic counts
425
const COUNTED_FILTERS = {
@@ -39,15 +60,14 @@ export default {
3960
"service:topic-tracking-state"
4061
);
4162

42-
for (const {
43-
display_name: displayName,
44-
title,
45-
url,
46-
} of settings.nav_links) {
63+
for (const link of settings.nav_links) {
64+
const { display_name: displayName, url } = link;
65+
const localizedDisplayName = getLocalizedField(link, "display_name");
66+
const localizedTitle = getLocalizedField(link, "title");
4767
const filterType = COUNTED_FILTERS[url];
4868
const itemConfig = {
4969
name: `custom_${displayName.replace(/\s+/g, "-").toLowerCase()}`,
50-
title,
70+
title: localizedTitle,
5171
href: url,
5272
forceActive: (category, args, router) =>
5373
router.currentURL?.split("?")[0] === url,
@@ -58,10 +78,12 @@ export default {
5878
// reactively, picking up count changes from TopicTrackingState
5979
itemConfig.displayName = () => {
6080
const count = getCountForFilter(topicTrackingState, filterType);
61-
return count > 0 ? `${displayName} (${count})` : displayName;
81+
return count > 0
82+
? `${localizedDisplayName} (${count})`
83+
: localizedDisplayName;
6284
};
6385
} else {
64-
itemConfig.displayName = displayName;
86+
itemConfig.displayName = localizedDisplayName;
6587
}
6688

6789
api.addNavigationBarItem(itemConfig);

locales/en.yml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,16 @@ en:
1414
url:
1515
label: URL
1616
description: The link (e.g., /latest or https://discourse.org)
17+
translations:
18+
label: Translations
19+
description: Per-language overrides for display name and title
20+
properties:
21+
locale:
22+
label: Language
23+
description: Select the language for this translation
24+
display_name:
25+
label: Display name
26+
description: Translated display name for this language
27+
title:
28+
label: Title
29+
description: Translated title (hover text) for this language

settings.yml

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,73 @@ nav_links:
3232
min_length: 1
3333
max_length: 2048
3434
url: true
35+
translations:
36+
type: objects
37+
schema:
38+
name: translation
39+
identifier: locale
40+
properties:
41+
locale:
42+
type: enum
43+
required: true
44+
choices:
45+
- ar
46+
- be
47+
- bg
48+
- bs_BA
49+
- ca
50+
- cs
51+
- da
52+
- de
53+
- el
54+
- en
55+
- en_GB
56+
- es
57+
- et
58+
- fa_IR
59+
- fi
60+
- fr
61+
- gl
62+
- he
63+
- hr
64+
- hu
65+
- hy
66+
- id
67+
- it
68+
- ja
69+
- ko
70+
- lt
71+
- lv
72+
- nb_NO
73+
- nl
74+
- pl_PL
75+
- pt
76+
- pt_BR
77+
- ro
78+
- ru
79+
- sk
80+
- sl
81+
- sq
82+
- sr
83+
- sv
84+
- sw
85+
- te
86+
- th
87+
- tr_TR
88+
- ug
89+
- uk
90+
- ur
91+
- vi
92+
- zh_CN
93+
- zh_TW
94+
display_name:
95+
type: string
96+
validations:
97+
max_length: 100
98+
title:
99+
type: string
100+
validations:
101+
max_length: 1000
35102
Hide_dropdowns:
36103
default: false
37104
description:

0 commit comments

Comments
 (0)