|
| 1 | +/* |
| 2 | + * @flow strict |
| 3 | + * Copyright (C) 2025 MetaBrainz Foundation |
| 4 | + * |
| 5 | + * This file is part of MusicBrainz, the open internet music database, |
| 6 | + * and is licensed under the GPL version 2, or (at your option) any |
| 7 | + * later version: http://www.gnu.org/licenses/gpl-2.0.txt |
| 8 | + */ |
| 9 | + |
| 10 | + |
| 11 | +import * as React from "react"; |
| 12 | +import languageIcon from '../../images/homepage/language-icon.svg'; |
| 13 | +import { SanitizedCatalystContext } from '../../../context.mjs'; |
| 14 | +import { returnToCurrentPage } from '../../../utility/returnUri.js'; |
| 15 | +import { capitalize } from '../common/utility/strings.js'; |
| 16 | + |
| 17 | +function languageName( |
| 18 | + language: ?ServerLanguageT, |
| 19 | + selected: boolean, |
| 20 | +) { |
| 21 | + if (!language) { |
| 22 | + return ''; |
| 23 | + } |
| 24 | + |
| 25 | + const { |
| 26 | + id, |
| 27 | + native_language: nativeLanguage, |
| 28 | + native_territory: nativeTerritory, |
| 29 | + } = language; |
| 30 | + |
| 31 | + let text = `[${id}]`; |
| 32 | + |
| 33 | + if (nativeLanguage) { |
| 34 | + text = capitalize(nativeLanguage); |
| 35 | + |
| 36 | + if (nativeTerritory) { |
| 37 | + text += ' (' + capitalize(nativeTerritory) + ')'; |
| 38 | + } |
| 39 | + } |
| 40 | + |
| 41 | + if (selected) { |
| 42 | + text += ' \u25be'; |
| 43 | + } |
| 44 | + |
| 45 | + return text; |
| 46 | +} |
| 47 | + |
| 48 | +component LanguageSelector() { |
| 49 | + const $c = React.useContext(SanitizedCatalystContext); |
| 50 | + const serverLanguages = $c.stash.server_languages; |
| 51 | + const currentLanguage = $c.stash.current_language.replace('_', '-'); |
| 52 | + |
| 53 | + return ( |
| 54 | + <> |
| 55 | + <a |
| 56 | + className="dropdown-toggle align-items-center dropdown-toggle-no-caret" |
| 57 | + href="#" |
| 58 | + role="button" |
| 59 | + data-bs-toggle="dropdown" |
| 60 | + aria-expanded="false" |
| 61 | + > |
| 62 | + <img src={languageIcon} alt="Language" width={40} height={40} /> |
| 63 | + </a> |
| 64 | + <ul className="dropdown-menu"> |
| 65 | + {serverLanguages?.map((language) => { |
| 66 | + const isSelected = language.name === currentLanguage; |
| 67 | + return ( |
| 68 | + <li key={language.name}> |
| 69 | + <a |
| 70 | + href={`/set-language/${encodeURIComponent(language.name)}?${returnToCurrentPage($c)}`} |
| 71 | + className={`dropdown-item ${isSelected ? 'active' : ''}`} |
| 72 | + > |
| 73 | + {languageName(language, isSelected)} |
| 74 | + </a> |
| 75 | + </li> |
| 76 | + ); |
| 77 | + })} |
| 78 | + <li> |
| 79 | + <a href={`/set-language/unset?${returnToCurrentPage($c)}`} className="dropdown-item">{l('(reset language)')}</a> |
| 80 | + </li> |
| 81 | + <li className="dropdown-divider" /> |
| 82 | + <li> |
| 83 | + <a href="https://translations.metabrainz.org/projects/musicbrainz/" className="dropdown-item">{l('Help translate')}</a> |
| 84 | + </li> |
| 85 | + </ul> |
| 86 | + </> |
| 87 | + ) |
| 88 | +} |
| 89 | + |
| 90 | +export default (hydrate < React.PropsOf < LanguageSelector >> ( |
| 91 | + 'div', |
| 92 | + LanguageSelector, |
| 93 | +): component(...React.PropsOf < LanguageSelector >)); |
0 commit comments