From a77216c6623d976dd0c725e7b46f2cc1a22a2ed4 Mon Sep 17 00:00:00 2001 From: Sin-Kang Date: Sat, 14 Nov 2026 14:14:00 +0900 Subject: [PATCH 1/3] feat: sync Kannada consent messages --- assets/consent/messages.js | 774 +++++++++++++++++++------------------ 1 file changed, 399 insertions(+), 375 deletions(-) diff --git a/assets/consent/messages.js b/assets/consent/messages.js index 80ecff9..64ad98b 100644 --- a/assets/consent/messages.js +++ b/assets/consent/messages.js @@ -1,375 +1,399 @@ -/** - * Consent bar and settings strings, 14 locales — the same set devslab.kr and - * the open-source hub (devslab-kr.github.io) render. - * - * Korean and English are @devslab/site-kit's CONSENT_MESSAGES_KO / _EN word - * for word (a test pins that); the other twelve say the same short things in - * the same neutral tone (owner decision 2026-10-06, DDS D-034): what is - * collected and why, that it is optional, and a "learn more" link. The full - * disclosure — Google Analytics 4, Google LLC, the transfer to the United - * States, 14 months, no ads, how to withdraw — is not here: it lives in the - * privacy policy section the bar's learnMore link opens - * (devslab.kr/privacy#processors, which covers both sites). The settings - * intro names the footer control by that locale's own `trigger` label. - * - * Shared file: the hub vendors a byte-identical copy at - * assets/consent/messages.js. Change both together. - */ - -/** @typedef {Record<'regionLabel'|'title'|'body'|'learnMore'|'privacyLink'|'acceptAll'|'rejectAll'|'settings'|'dismiss'|'settingsTitle'|'settingsIntro'|'necessaryTitle'|'necessaryBody'|'necessaryStatus'|'analyticsTitle'|'analyticsBody'|'analyticsSwitch'|'save'|'cancel'|'close'|'saved'|'trigger', string>} ConsentMessages */ - -/** @type {Readonly>>} */ -export const CONSENT_MESSAGES = Object.freeze({ - ko: Object.freeze({ - regionLabel: '쿠키 동의', - title: '이용 통계 수집 동의 (선택)', - body: '서비스를 더 낫게 만들기 위해 이용 통계를 수집합니다. 동의는 선택이며, 동의하지 않아도 모든 기능을 쓸 수 있습니다.', - learnMore: '자세히 보기', - privacyLink: '개인정보처리방침', - acceptAll: '모두 허용', - rejectAll: '거부', - settings: '설정', - dismiss: '선택하지 않고 닫기', - settingsTitle: '쿠키 설정', - settingsIntro: '바닥글의 ‘쿠키 설정’에서 언제든 다시 바꿀 수 있습니다.', - necessaryTitle: '필수', - necessaryBody: '사이트가 동작하는 데 꼭 필요해 항상 사용합니다.', - necessaryStatus: '항상 사용', - analyticsTitle: '이용 통계 (선택)', - analyticsBody: '서비스를 개선하는 데 쓰는 이용 통계입니다.', - analyticsSwitch: '이용 통계 수집 허용', - save: '선택 저장', - cancel: '취소', - close: '닫기', - saved: '쿠키 설정을 저장했습니다.', - trigger: '쿠키 설정', - }), - en: Object.freeze({ - regionLabel: 'Cookie consent', - title: 'Analytics (optional)', - body: "We collect usage statistics to improve the service. It's optional, and everything works without it.", - learnMore: 'Learn more', - privacyLink: 'Privacy policy', - acceptAll: 'Accept all', - rejectAll: 'Reject', - settings: 'Settings', - dismiss: 'Close without choosing', - settingsTitle: 'Cookie settings', - settingsIntro: 'You can change this at any time under “Cookie settings” in the footer.', - necessaryTitle: 'Necessary', - necessaryBody: 'Needed for the site to work, so always on.', - necessaryStatus: 'Always on', - analyticsTitle: 'Analytics (optional)', - analyticsBody: 'Usage statistics that help us improve the service.', - analyticsSwitch: 'Allow analytics', - save: 'Save choices', - cancel: 'Cancel', - close: 'Close', - saved: 'Your cookie settings are saved.', - trigger: 'Cookie settings', - }), - ja: Object.freeze({ - regionLabel: 'Cookieの同意', - title: '利用統計の収集への同意(任意)', - body: 'サービスの改善のため、利用統計を収集します。同意は任意で、同意しなくてもすべての機能をご利用いただけます。', - learnMore: '詳しく見る', - privacyLink: 'プライバシーポリシー', - acceptAll: 'すべて許可', - rejectAll: '拒否', - settings: '設定', - dismiss: '選ばずに閉じる', - settingsTitle: 'Cookie設定', - settingsIntro: 'フッターの「Cookie設定」からいつでも変更できます。', - necessaryTitle: '必須', - necessaryBody: 'サイトの動作に欠かせないため、常に使用します。', - necessaryStatus: '常に使用', - analyticsTitle: '利用統計(任意)', - analyticsBody: 'サービスの改善に使う利用統計です。', - analyticsSwitch: '利用統計の収集を許可', - save: '選択を保存', - cancel: 'キャンセル', - close: '閉じる', - saved: 'Cookie設定を保存しました。', - trigger: 'Cookie設定', - }), - 'zh-HK': Object.freeze({ - regionLabel: 'Cookie 同意', - title: '同意收集使用統計(可選)', - body: '我們會收集使用統計,以改善服務。是否同意由你決定,即使不同意,所有功能仍可照常使用。', - learnMore: '了解更多', - privacyLink: '私隱政策', - acceptAll: '全部允許', - rejectAll: '拒絕', - settings: '設定', - dismiss: '不作選擇並關閉', - settingsTitle: 'Cookie 設定', - settingsIntro: '你可隨時在頁尾的「Cookie 設定」更改選擇。', - necessaryTitle: '必要', - necessaryBody: '網站運作所必需,因此一直使用。', - necessaryStatus: '一直使用', - analyticsTitle: '使用統計(可選)', - analyticsBody: '用於改善服務的使用統計。', - analyticsSwitch: '允許收集使用統計', - save: '儲存選擇', - cancel: '取消', - close: '關閉', - saved: '已儲存 Cookie 設定。', - trigger: 'Cookie 設定', - }), - 'zh-TW': Object.freeze({ - regionLabel: 'Cookie 同意', - title: '同意收集使用統計(選用)', - body: '我們會收集使用統計,以改善服務。是否同意由您決定,即使不同意,所有功能仍可正常使用。', - learnMore: '瞭解詳情', - privacyLink: '隱私權政策', - acceptAll: '全部允許', - rejectAll: '拒絕', - settings: '設定', - dismiss: '不選擇並關閉', - settingsTitle: 'Cookie 設定', - settingsIntro: '您可以隨時在頁尾的「Cookie 設定」變更選擇。', - necessaryTitle: '必要', - necessaryBody: '網站運作所必需,因此一律使用。', - necessaryStatus: '一律使用', - analyticsTitle: '使用統計(選用)', - analyticsBody: '用於改善服務的使用統計。', - analyticsSwitch: '允許收集使用統計', - save: '儲存選擇', - cancel: '取消', - close: '關閉', - saved: '已儲存 Cookie 設定。', - trigger: 'Cookie 設定', - }), - hi: Object.freeze({ - regionLabel: 'कुकी सहमति', - title: 'उपयोग के आँकड़े (वैकल्पिक)', - body: 'सेवा को बेहतर बनाने के लिए हम उपयोग के आँकड़े इकट्ठा करते हैं। यह वैकल्पिक है, और इसके बिना भी सब कुछ काम करता है।', - learnMore: 'और जानें', - privacyLink: 'गोपनीयता नीति', - acceptAll: 'सभी स्वीकार करें', - rejectAll: 'अस्वीकार करें', - settings: 'सेटिंग', - dismiss: 'बिना चुने बंद करें', - settingsTitle: 'कुकी सेटिंग', - settingsIntro: 'आप फ़ुटर में “कुकी सेटिंग” से इसे कभी भी बदल सकते हैं।', - necessaryTitle: 'आवश्यक', - necessaryBody: 'साइट के काम करने के लिए ज़रूरी हैं, इसलिए हमेशा चालू रहती हैं।', - necessaryStatus: 'हमेशा चालू', - analyticsTitle: 'उपयोग के आँकड़े (वैकल्पिक)', - analyticsBody: 'उपयोग के आँकड़े, जिनसे हमें सेवा बेहतर बनाने में मदद मिलती है।', - analyticsSwitch: 'उपयोग के आँकड़ों की अनुमति दें', - save: 'चुनाव सहेजें', - cancel: 'रद्द करें', - close: 'बंद करें', - saved: 'आपकी कुकी सेटिंग सहेज ली गई है।', - trigger: 'कुकी सेटिंग', - }), - vi: Object.freeze({ - regionLabel: 'Đồng ý cookie', - title: 'Thống kê sử dụng (tùy chọn)', - body: 'Chúng tôi thu thập số liệu thống kê sử dụng để cải thiện dịch vụ. Việc này là tùy chọn, và mọi tính năng vẫn hoạt động khi bạn không đồng ý.', - learnMore: 'Tìm hiểu thêm', - privacyLink: 'Chính sách quyền riêng tư', - acceptAll: 'Chấp nhận tất cả', - rejectAll: 'Từ chối', - settings: 'Cài đặt', - dismiss: 'Đóng mà không chọn', - settingsTitle: 'Cài đặt cookie', - settingsIntro: 'Bạn có thể thay đổi lựa chọn bất cứ lúc nào tại “Cài đặt cookie” ở chân trang.', - necessaryTitle: 'Cần thiết', - necessaryBody: 'Cần để trang hoạt động, nên luôn được bật.', - necessaryStatus: 'Luôn bật', - analyticsTitle: 'Thống kê sử dụng (tùy chọn)', - analyticsBody: 'Số liệu thống kê sử dụng giúp chúng tôi cải thiện dịch vụ.', - analyticsSwitch: 'Cho phép thống kê sử dụng', - save: 'Lưu lựa chọn', - cancel: 'Hủy', - close: 'Đóng', - saved: 'Đã lưu cài đặt cookie của bạn.', - trigger: 'Cài đặt cookie', - }), - id: Object.freeze({ - regionLabel: 'Persetujuan cookie', - title: 'Statistik penggunaan (opsional)', - body: 'Kami mengumpulkan statistik penggunaan untuk meningkatkan layanan. Ini opsional, dan semua fitur tetap berfungsi tanpanya.', - learnMore: 'Pelajari lebih lanjut', - privacyLink: 'Kebijakan Privasi', - acceptAll: 'Terima semua', - rejectAll: 'Tolak', - settings: 'Pengaturan', - dismiss: 'Tutup tanpa memilih', - settingsTitle: 'Pengaturan cookie', - settingsIntro: 'Anda dapat mengubahnya kapan saja melalui “Pengaturan cookie” di footer.', - necessaryTitle: 'Diperlukan', - necessaryBody: 'Dibutuhkan agar situs berfungsi, jadi selalu aktif.', - necessaryStatus: 'Selalu aktif', - analyticsTitle: 'Statistik penggunaan (opsional)', - analyticsBody: 'Statistik penggunaan yang membantu kami meningkatkan layanan.', - analyticsSwitch: 'Izinkan statistik penggunaan', - save: 'Simpan pilihan', - cancel: 'Batal', - close: 'Tutup', - saved: 'Pengaturan cookie Anda telah disimpan.', - trigger: 'Pengaturan cookie', - }), - th: Object.freeze({ - regionLabel: 'ความยินยอมคุกกี้', - title: 'สถิติการใช้งาน (ไม่บังคับ)', - body: 'เราเก็บสถิติการใช้งานเพื่อปรับปรุงบริการ การยินยอมเป็นทางเลือก และทุกฟังก์ชันใช้งานได้แม้ไม่ยินยอม', - learnMore: 'ดูรายละเอียด', - privacyLink: 'นโยบายความเป็นส่วนตัว', - acceptAll: 'ยอมรับทั้งหมด', - rejectAll: 'ปฏิเสธ', - settings: 'ตั้งค่า', - dismiss: 'ปิดโดยไม่เลือก', - settingsTitle: 'การตั้งค่าคุกกี้', - settingsIntro: 'คุณเปลี่ยนตัวเลือกได้ทุกเมื่อที่ “การตั้งค่าคุกกี้” ในส่วนท้ายของหน้า', - necessaryTitle: 'จำเป็น', - necessaryBody: 'จำเป็นต่อการทำงานของเว็บไซต์ จึงเปิดใช้เสมอ', - necessaryStatus: 'เปิดใช้เสมอ', - analyticsTitle: 'สถิติการใช้งาน (ไม่บังคับ)', - analyticsBody: 'สถิติการใช้งานที่ช่วยให้เราปรับปรุงบริการ', - analyticsSwitch: 'อนุญาตสถิติการใช้งาน', - save: 'บันทึกตัวเลือก', - cancel: 'ยกเลิก', - close: 'ปิด', - saved: 'บันทึกการตั้งค่าคุกกี้แล้ว', - trigger: 'การตั้งค่าคุกกี้', - }), - 'pt-BR': Object.freeze({ - regionLabel: 'Consentimento de cookies', - title: 'Estatísticas de uso (opcional)', - body: 'Coletamos estatísticas de uso para melhorar o serviço. É opcional, e tudo funciona sem isso.', - learnMore: 'Saiba mais', - privacyLink: 'Política de Privacidade', - acceptAll: 'Aceitar todos', - rejectAll: 'Recusar', - settings: 'Configurações', - dismiss: 'Fechar sem escolher', - settingsTitle: 'Configurações de cookies', - settingsIntro: 'Você pode mudar isso a qualquer momento em “Configurações de cookies”, no rodapé.', - necessaryTitle: 'Necessários', - necessaryBody: 'Necessários para o site funcionar, por isso estão sempre ativos.', - necessaryStatus: 'Sempre ativos', - analyticsTitle: 'Estatísticas de uso (opcional)', - analyticsBody: 'Estatísticas de uso que nos ajudam a melhorar o serviço.', - analyticsSwitch: 'Permitir estatísticas de uso', - save: 'Salvar escolhas', - cancel: 'Cancelar', - close: 'Fechar', - saved: 'Suas configurações de cookies foram salvas.', - trigger: 'Configurações de cookies', - }), - fr: Object.freeze({ - regionLabel: 'Consentement aux cookies', - title: 'Mesure d’audience (facultatif)', - body: 'Nous recueillons des statistiques d’utilisation pour améliorer le service. C’est facultatif, et tout fonctionne sans.', - learnMore: 'En savoir plus', - privacyLink: 'Politique de confidentialité', - acceptAll: 'Tout accepter', - rejectAll: 'Refuser', - settings: 'Paramètres', - dismiss: 'Fermer sans choisir', - settingsTitle: 'Paramètres des cookies', - settingsIntro: 'Vous pouvez modifier ce choix à tout moment via « Paramètres des cookies » en bas de page.', - necessaryTitle: 'Nécessaires', - necessaryBody: 'Indispensables au fonctionnement du site, donc toujours actifs.', - necessaryStatus: 'Toujours actifs', - analyticsTitle: 'Mesure d’audience (facultatif)', - analyticsBody: 'Des statistiques d’utilisation qui nous aident à améliorer le service.', - analyticsSwitch: 'Autoriser la mesure d’audience', - save: 'Enregistrer mes choix', - cancel: 'Annuler', - close: 'Fermer', - saved: 'Vos paramètres de cookies sont enregistrés.', - trigger: 'Paramètres des cookies', - }), - de: Object.freeze({ - regionLabel: 'Cookie-Einwilligung', - title: 'Nutzungsstatistik (optional)', - body: 'Wir erfassen Nutzungsstatistiken, um den Dienst zu verbessern. Das ist freiwillig, und alles funktioniert auch ohne.', - learnMore: 'Mehr erfahren', - privacyLink: 'Datenschutzerklärung', - acceptAll: 'Alle akzeptieren', - rejectAll: 'Ablehnen', - settings: 'Einstellungen', - dismiss: 'Ohne Auswahl schließen', - settingsTitle: 'Cookie-Einstellungen', - settingsIntro: 'Unter „Cookie-Einstellungen“ in der Fußzeile können Sie das jederzeit ändern.', - necessaryTitle: 'Notwendig', - necessaryBody: 'Für den Betrieb der Website erforderlich und daher immer aktiv.', - necessaryStatus: 'Immer aktiv', - analyticsTitle: 'Nutzungsstatistik (optional)', - analyticsBody: 'Nutzungsstatistiken, die uns helfen, den Dienst zu verbessern.', - analyticsSwitch: 'Nutzungsstatistik erlauben', - save: 'Auswahl speichern', - cancel: 'Abbrechen', - close: 'Schließen', - saved: 'Ihre Cookie-Einstellungen wurden gespeichert.', - trigger: 'Cookie-Einstellungen', - }), - es: Object.freeze({ - regionLabel: 'Consentimiento de cookies', - title: 'Estadísticas de uso (opcional)', - body: 'Recopilamos estadísticas de uso para mejorar el servicio. Es opcional, y todo funciona sin ello.', - learnMore: 'Más información', - privacyLink: 'Política de privacidad', - acceptAll: 'Aceptar todo', - rejectAll: 'Rechazar', - settings: 'Configuración', - dismiss: 'Cerrar sin elegir', - settingsTitle: 'Configuración de cookies', - settingsIntro: 'Puedes cambiarlo en cualquier momento en «Configuración de cookies», en el pie de página.', - necessaryTitle: 'Necesarias', - necessaryBody: 'Imprescindibles para que el sitio funcione, por eso siempre están activas.', - necessaryStatus: 'Siempre activas', - analyticsTitle: 'Estadísticas de uso (opcional)', - analyticsBody: 'Estadísticas de uso que nos ayudan a mejorar el servicio.', - analyticsSwitch: 'Permitir estadísticas de uso', - save: 'Guardar elección', - cancel: 'Cancelar', - close: 'Cerrar', - saved: 'Se ha guardado tu configuración de cookies.', - trigger: 'Configuración de cookies', - }), - ar: Object.freeze({ - regionLabel: 'الموافقة على ملفات تعريف الارتباط', - title: 'إحصاءات الاستخدام (اختيارية)', - body: 'نجمع إحصاءات الاستخدام لتحسين الخدمة. الموافقة اختيارية، ويعمل كل شيء بدونها.', - learnMore: 'اعرف المزيد', - privacyLink: 'سياسة الخصوصية', - acceptAll: 'قبول الكل', - rejectAll: 'رفض', - settings: 'الإعدادات', - dismiss: 'إغلاق دون اختيار', - settingsTitle: 'إعدادات ملفات تعريف الارتباط', - settingsIntro: 'يمكنك تغيير ذلك في أي وقت من «إعدادات ملفات تعريف الارتباط» في تذييل الصفحة.', - necessaryTitle: 'ضرورية', - necessaryBody: 'لازمة لعمل الموقع، لذلك تظل مفعّلة دائمًا.', - necessaryStatus: 'مفعّلة دائمًا', - analyticsTitle: 'إحصاءات الاستخدام (اختيارية)', - analyticsBody: 'إحصاءات استخدام تساعدنا على تحسين الخدمة.', - analyticsSwitch: 'السماح بإحصاءات الاستخدام', - save: 'حفظ الاختيارات', - cancel: 'إلغاء', - close: 'إغلاق', - saved: 'تم حفظ إعدادات ملفات تعريف الارتباط.', - trigger: 'إعدادات ملفات تعريف الارتباط', - }), -}); - -/** - * Strings for a document language: the exact tag, then its base language - * (zh falls to zh-TW only through an explicit tag — a bare `zh` reads - * English, as the site does not serve Simplified Chinese), else English. - * @param {string | null | undefined} lang - * @returns {{ lang: string, messages: Readonly }} - */ -export function consentMessagesFor(lang) { - const tag = typeof lang === 'string' ? lang.trim() : ''; - const exact = Object.keys(CONSENT_MESSAGES).find((key) => key.toLowerCase() === tag.toLowerCase()); - if (exact) return { lang: exact, messages: CONSENT_MESSAGES[exact] }; - const base = tag.split('-')[0].toLowerCase(); - if (base && base !== 'zh' && CONSENT_MESSAGES[base]) return { lang: base, messages: CONSENT_MESSAGES[base] }; - return { lang: 'en', messages: CONSENT_MESSAGES.en }; -} +/** + * Consent bar and settings strings, including Kannada. Shared by devslab.kr and + * the open-source hub (devslab-kr.github.io). + * + * Korean and English are @devslab/site-kit's CONSENT_MESSAGES_KO / _EN word + * for word (a test pins that); the other locales say the same short things in + * the same neutral tone (owner decision 2026-10-06, DDS D-034): what is + * collected and why, that it is optional, and a "learn more" link. The full + * disclosure — Google Analytics 4, Google LLC, the transfer to the United + * States, 14 months, no ads, how to withdraw — is not here: it lives in the + * privacy policy section the bar's learnMore link opens + * (devslab.kr/privacy#processors, which covers both sites). The settings + * intro names the footer control by that locale's own `trigger` label. + * + * Shared file: the hub vendors a byte-identical copy at + * assets/consent/messages.js. Change both together. + */ + +/** @typedef {Record<'regionLabel'|'title'|'body'|'learnMore'|'privacyLink'|'acceptAll'|'rejectAll'|'settings'|'dismiss'|'settingsTitle'|'settingsIntro'|'necessaryTitle'|'necessaryBody'|'necessaryStatus'|'analyticsTitle'|'analyticsBody'|'analyticsSwitch'|'save'|'cancel'|'close'|'saved'|'trigger', string>} ConsentMessages */ + +/** @type {Readonly>>} */ +export const CONSENT_MESSAGES = Object.freeze({ + ko: Object.freeze({ + regionLabel: '쿠키 동의', + title: '이용 통계 수집 동의 (선택)', + body: '서비스를 더 낫게 만들기 위해 이용 통계를 수집합니다. 동의는 선택이며, 동의하지 않아도 모든 기능을 쓸 수 있습니다.', + learnMore: '자세히 보기', + privacyLink: '개인정보처리방침', + acceptAll: '모두 허용', + rejectAll: '거부', + settings: '설정', + dismiss: '선택하지 않고 닫기', + settingsTitle: '쿠키 설정', + settingsIntro: '바닥글의 ‘쿠키 설정’에서 언제든 다시 바꿀 수 있습니다.', + necessaryTitle: '필수', + necessaryBody: '사이트가 동작하는 데 꼭 필요해 항상 사용합니다.', + necessaryStatus: '항상 사용', + analyticsTitle: '이용 통계 (선택)', + analyticsBody: '서비스를 개선하는 데 쓰는 이용 통계입니다.', + analyticsSwitch: '이용 통계 수집 허용', + save: '선택 저장', + cancel: '취소', + close: '닫기', + saved: '쿠키 설정을 저장했습니다.', + trigger: '쿠키 설정', + }), + en: Object.freeze({ + regionLabel: 'Cookie consent', + title: 'Analytics (optional)', + body: "We collect usage statistics to improve the service. It's optional, and everything works without it.", + learnMore: 'Learn more', + privacyLink: 'Privacy policy', + acceptAll: 'Accept all', + rejectAll: 'Reject', + settings: 'Settings', + dismiss: 'Close without choosing', + settingsTitle: 'Cookie settings', + settingsIntro: 'You can change this at any time under “Cookie settings” in the footer.', + necessaryTitle: 'Necessary', + necessaryBody: 'Needed for the site to work, so always on.', + necessaryStatus: 'Always on', + analyticsTitle: 'Analytics (optional)', + analyticsBody: 'Usage statistics that help us improve the service.', + analyticsSwitch: 'Allow analytics', + save: 'Save choices', + cancel: 'Cancel', + close: 'Close', + saved: 'Your cookie settings are saved.', + trigger: 'Cookie settings', + }), + ja: Object.freeze({ + regionLabel: 'Cookieの同意', + title: '利用統計の収集への同意(任意)', + body: 'サービスの改善のため、利用統計を収集します。同意は任意で、同意しなくてもすべての機能をご利用いただけます。', + learnMore: '詳しく見る', + privacyLink: 'プライバシーポリシー', + acceptAll: 'すべて許可', + rejectAll: '拒否', + settings: '設定', + dismiss: '選ばずに閉じる', + settingsTitle: 'Cookie設定', + settingsIntro: 'フッターの「Cookie設定」からいつでも変更できます。', + necessaryTitle: '必須', + necessaryBody: 'サイトの動作に欠かせないため、常に使用します。', + necessaryStatus: '常に使用', + analyticsTitle: '利用統計(任意)', + analyticsBody: 'サービスの改善に使う利用統計です。', + analyticsSwitch: '利用統計の収集を許可', + save: '選択を保存', + cancel: 'キャンセル', + close: '閉じる', + saved: 'Cookie設定を保存しました。', + trigger: 'Cookie設定', + }), + 'zh-HK': Object.freeze({ + regionLabel: 'Cookie 同意', + title: '同意收集使用統計(可選)', + body: '我們會收集使用統計,以改善服務。是否同意由你決定,即使不同意,所有功能仍可照常使用。', + learnMore: '了解更多', + privacyLink: '私隱政策', + acceptAll: '全部允許', + rejectAll: '拒絕', + settings: '設定', + dismiss: '不作選擇並關閉', + settingsTitle: 'Cookie 設定', + settingsIntro: '你可隨時在頁尾的「Cookie 設定」更改選擇。', + necessaryTitle: '必要', + necessaryBody: '網站運作所必需,因此一直使用。', + necessaryStatus: '一直使用', + analyticsTitle: '使用統計(可選)', + analyticsBody: '用於改善服務的使用統計。', + analyticsSwitch: '允許收集使用統計', + save: '儲存選擇', + cancel: '取消', + close: '關閉', + saved: '已儲存 Cookie 設定。', + trigger: 'Cookie 設定', + }), + 'zh-TW': Object.freeze({ + regionLabel: 'Cookie 同意', + title: '同意收集使用統計(選用)', + body: '我們會收集使用統計,以改善服務。是否同意由您決定,即使不同意,所有功能仍可正常使用。', + learnMore: '瞭解詳情', + privacyLink: '隱私權政策', + acceptAll: '全部允許', + rejectAll: '拒絕', + settings: '設定', + dismiss: '不選擇並關閉', + settingsTitle: 'Cookie 設定', + settingsIntro: '您可以隨時在頁尾的「Cookie 設定」變更選擇。', + necessaryTitle: '必要', + necessaryBody: '網站運作所必需,因此一律使用。', + necessaryStatus: '一律使用', + analyticsTitle: '使用統計(選用)', + analyticsBody: '用於改善服務的使用統計。', + analyticsSwitch: '允許收集使用統計', + save: '儲存選擇', + cancel: '取消', + close: '關閉', + saved: '已儲存 Cookie 設定。', + trigger: 'Cookie 設定', + }), + kn: Object.freeze({ + regionLabel: 'ಕುಕೀ ಸಮ್ಮತಿ', + title: 'ಬಳಕೆಯ ಅಂಕಿಅಂಶಗಳು (ಐಚ್ಛಿಕ)', + body: 'ಸೇವೆಯನ್ನು ಸುಧಾರಿಸಲು ಬಳಕೆಯ ಅಂಕಿಅಂಶಗಳನ್ನು ಸಂಗ್ರಹಿಸುತ್ತೇವೆ. ಇದು ಐಚ್ಛಿಕ. ಒಪ್ಪದಿದ್ದರೂ ಎಲ್ಲ ಸೌಲಭ್ಯಗಳನ್ನು ಬಳಸಬಹುದು.', + learnMore: 'ಇನ್ನಷ್ಟು ತಿಳಿಯಿರಿ', + privacyLink: 'ಗೌಪ್ಯತಾ ನೀತಿ', + acceptAll: 'ಎಲ್ಲವನ್ನೂ ಒಪ್ಪಿ', + rejectAll: 'ನಿರಾಕರಿಸಿ', + settings: 'ಸೆಟ್ಟಿಂಗ್‌ಗಳು', + dismiss: 'ಆಯ್ಕೆ ಮಾಡದೆ ಮುಚ್ಚಿ', + settingsTitle: 'ಕುಕೀ ಸೆಟ್ಟಿಂಗ್‌ಗಳು', + settingsIntro: 'ಪುಟದ ಕೆಳಗಿನ “ಕುಕೀ ಸೆಟ್ಟಿಂಗ್‌ಗಳು” ಮೂಲಕ ಯಾವಾಗ ಬೇಕಾದರೂ ಬದಲಾಯಿಸಬಹುದು.', + necessaryTitle: 'ಅಗತ್ಯ', + necessaryBody: 'ಸೈಟ್ ಕಾರ್ಯನಿರ್ವಹಿಸಲು ಅಗತ್ಯವಾದ್ದರಿಂದ ಯಾವಾಗಲೂ ಸಕ್ರಿಯವಾಗಿರುತ್ತವೆ.', + necessaryStatus: 'ಯಾವಾಗಲೂ ಸಕ್ರಿಯ', + analyticsTitle: 'ಬಳಕೆಯ ಅಂಕಿಅಂಶಗಳು (ಐಚ್ಛಿಕ)', + analyticsBody: 'ಸೇವೆಯನ್ನು ಸುಧಾರಿಸಲು ನೆರವಾಗುವ ಬಳಕೆಯ ಅಂಕಿಅಂಶಗಳು.', + analyticsSwitch: 'ಬಳಕೆಯ ಅಂಕಿಅಂಶ ಸಂಗ್ರಹಕ್ಕೆ ಅನುಮತಿಸಿ', + save: 'ಆಯ್ಕೆಗಳನ್ನು ಉಳಿಸಿ', + cancel: 'ರದ್ದುಮಾಡಿ', + close: 'ಮುಚ್ಚಿ', + saved: 'ಕುಕೀ ಸೆಟ್ಟಿಂಗ್‌ಗಳನ್ನು ಉಳಿಸಲಾಗಿದೆ.', + trigger: 'ಕುಕೀ ಸೆಟ್ಟಿಂಗ್‌ಗಳು', + }), + hi: Object.freeze({ + regionLabel: 'कुकी सहमति', + title: 'उपयोग के आँकड़े (वैकल्पिक)', + body: 'सेवा को बेहतर बनाने के लिए हम उपयोग के आँकड़े इकट्ठा करते हैं। यह वैकल्पिक है, और इसके बिना भी सब कुछ काम करता है।', + learnMore: 'और जानें', + privacyLink: 'गोपनीयता नीति', + acceptAll: 'सभी स्वीकार करें', + rejectAll: 'अस्वीकार करें', + settings: 'सेटिंग', + dismiss: 'बिना चुने बंद करें', + settingsTitle: 'कुकी सेटिंग', + settingsIntro: 'आप फ़ुटर में “कुकी सेटिंग” से इसे कभी भी बदल सकते हैं।', + necessaryTitle: 'आवश्यक', + necessaryBody: 'साइट के काम करने के लिए ज़रूरी हैं, इसलिए हमेशा चालू रहती हैं।', + necessaryStatus: 'हमेशा चालू', + analyticsTitle: 'उपयोग के आँकड़े (वैकल्पिक)', + analyticsBody: 'उपयोग के आँकड़े, जिनसे हमें सेवा बेहतर बनाने में मदद मिलती है।', + analyticsSwitch: 'उपयोग के आँकड़ों की अनुमति दें', + save: 'चुनाव सहेजें', + cancel: 'रद्द करें', + close: 'बंद करें', + saved: 'आपकी कुकी सेटिंग सहेज ली गई है।', + trigger: 'कुकी सेटिंग', + }), + vi: Object.freeze({ + regionLabel: 'Đồng ý cookie', + title: 'Thống kê sử dụng (tùy chọn)', + body: 'Chúng tôi thu thập số liệu thống kê sử dụng để cải thiện dịch vụ. Việc này là tùy chọn, và mọi tính năng vẫn hoạt động khi bạn không đồng ý.', + learnMore: 'Tìm hiểu thêm', + privacyLink: 'Chính sách quyền riêng tư', + acceptAll: 'Chấp nhận tất cả', + rejectAll: 'Từ chối', + settings: 'Cài đặt', + dismiss: 'Đóng mà không chọn', + settingsTitle: 'Cài đặt cookie', + settingsIntro: 'Bạn có thể thay đổi lựa chọn bất cứ lúc nào tại “Cài đặt cookie” ở chân trang.', + necessaryTitle: 'Cần thiết', + necessaryBody: 'Cần để trang hoạt động, nên luôn được bật.', + necessaryStatus: 'Luôn bật', + analyticsTitle: 'Thống kê sử dụng (tùy chọn)', + analyticsBody: 'Số liệu thống kê sử dụng giúp chúng tôi cải thiện dịch vụ.', + analyticsSwitch: 'Cho phép thống kê sử dụng', + save: 'Lưu lựa chọn', + cancel: 'Hủy', + close: 'Đóng', + saved: 'Đã lưu cài đặt cookie của bạn.', + trigger: 'Cài đặt cookie', + }), + id: Object.freeze({ + regionLabel: 'Persetujuan cookie', + title: 'Statistik penggunaan (opsional)', + body: 'Kami mengumpulkan statistik penggunaan untuk meningkatkan layanan. Ini opsional, dan semua fitur tetap berfungsi tanpanya.', + learnMore: 'Pelajari lebih lanjut', + privacyLink: 'Kebijakan Privasi', + acceptAll: 'Terima semua', + rejectAll: 'Tolak', + settings: 'Pengaturan', + dismiss: 'Tutup tanpa memilih', + settingsTitle: 'Pengaturan cookie', + settingsIntro: 'Anda dapat mengubahnya kapan saja melalui “Pengaturan cookie” di footer.', + necessaryTitle: 'Diperlukan', + necessaryBody: 'Dibutuhkan agar situs berfungsi, jadi selalu aktif.', + necessaryStatus: 'Selalu aktif', + analyticsTitle: 'Statistik penggunaan (opsional)', + analyticsBody: 'Statistik penggunaan yang membantu kami meningkatkan layanan.', + analyticsSwitch: 'Izinkan statistik penggunaan', + save: 'Simpan pilihan', + cancel: 'Batal', + close: 'Tutup', + saved: 'Pengaturan cookie Anda telah disimpan.', + trigger: 'Pengaturan cookie', + }), + th: Object.freeze({ + regionLabel: 'ความยินยอมคุกกี้', + title: 'สถิติการใช้งาน (ไม่บังคับ)', + body: 'เราเก็บสถิติการใช้งานเพื่อปรับปรุงบริการ การยินยอมเป็นทางเลือก และทุกฟังก์ชันใช้งานได้แม้ไม่ยินยอม', + learnMore: 'ดูรายละเอียด', + privacyLink: 'นโยบายความเป็นส่วนตัว', + acceptAll: 'ยอมรับทั้งหมด', + rejectAll: 'ปฏิเสธ', + settings: 'ตั้งค่า', + dismiss: 'ปิดโดยไม่เลือก', + settingsTitle: 'การตั้งค่าคุกกี้', + settingsIntro: 'คุณเปลี่ยนตัวเลือกได้ทุกเมื่อที่ “การตั้งค่าคุกกี้” ในส่วนท้ายของหน้า', + necessaryTitle: 'จำเป็น', + necessaryBody: 'จำเป็นต่อการทำงานของเว็บไซต์ จึงเปิดใช้เสมอ', + necessaryStatus: 'เปิดใช้เสมอ', + analyticsTitle: 'สถิติการใช้งาน (ไม่บังคับ)', + analyticsBody: 'สถิติการใช้งานที่ช่วยให้เราปรับปรุงบริการ', + analyticsSwitch: 'อนุญาตสถิติการใช้งาน', + save: 'บันทึกตัวเลือก', + cancel: 'ยกเลิก', + close: 'ปิด', + saved: 'บันทึกการตั้งค่าคุกกี้แล้ว', + trigger: 'การตั้งค่าคุกกี้', + }), + 'pt-BR': Object.freeze({ + regionLabel: 'Consentimento de cookies', + title: 'Estatísticas de uso (opcional)', + body: 'Coletamos estatísticas de uso para melhorar o serviço. É opcional, e tudo funciona sem isso.', + learnMore: 'Saiba mais', + privacyLink: 'Política de Privacidade', + acceptAll: 'Aceitar todos', + rejectAll: 'Recusar', + settings: 'Configurações', + dismiss: 'Fechar sem escolher', + settingsTitle: 'Configurações de cookies', + settingsIntro: 'Você pode mudar isso a qualquer momento em “Configurações de cookies”, no rodapé.', + necessaryTitle: 'Necessários', + necessaryBody: 'Necessários para o site funcionar, por isso estão sempre ativos.', + necessaryStatus: 'Sempre ativos', + analyticsTitle: 'Estatísticas de uso (opcional)', + analyticsBody: 'Estatísticas de uso que nos ajudam a melhorar o serviço.', + analyticsSwitch: 'Permitir estatísticas de uso', + save: 'Salvar escolhas', + cancel: 'Cancelar', + close: 'Fechar', + saved: 'Suas configurações de cookies foram salvas.', + trigger: 'Configurações de cookies', + }), + fr: Object.freeze({ + regionLabel: 'Consentement aux cookies', + title: 'Mesure d’audience (facultatif)', + body: 'Nous recueillons des statistiques d’utilisation pour améliorer le service. C’est facultatif, et tout fonctionne sans.', + learnMore: 'En savoir plus', + privacyLink: 'Politique de confidentialité', + acceptAll: 'Tout accepter', + rejectAll: 'Refuser', + settings: 'Paramètres', + dismiss: 'Fermer sans choisir', + settingsTitle: 'Paramètres des cookies', + settingsIntro: 'Vous pouvez modifier ce choix à tout moment via « Paramètres des cookies » en bas de page.', + necessaryTitle: 'Nécessaires', + necessaryBody: 'Indispensables au fonctionnement du site, donc toujours actifs.', + necessaryStatus: 'Toujours actifs', + analyticsTitle: 'Mesure d’audience (facultatif)', + analyticsBody: 'Des statistiques d’utilisation qui nous aident à améliorer le service.', + analyticsSwitch: 'Autoriser la mesure d’audience', + save: 'Enregistrer mes choix', + cancel: 'Annuler', + close: 'Fermer', + saved: 'Vos paramètres de cookies sont enregistrés.', + trigger: 'Paramètres des cookies', + }), + de: Object.freeze({ + regionLabel: 'Cookie-Einwilligung', + title: 'Nutzungsstatistik (optional)', + body: 'Wir erfassen Nutzungsstatistiken, um den Dienst zu verbessern. Das ist freiwillig, und alles funktioniert auch ohne.', + learnMore: 'Mehr erfahren', + privacyLink: 'Datenschutzerklärung', + acceptAll: 'Alle akzeptieren', + rejectAll: 'Ablehnen', + settings: 'Einstellungen', + dismiss: 'Ohne Auswahl schließen', + settingsTitle: 'Cookie-Einstellungen', + settingsIntro: 'Unter „Cookie-Einstellungen“ in der Fußzeile können Sie das jederzeit ändern.', + necessaryTitle: 'Notwendig', + necessaryBody: 'Für den Betrieb der Website erforderlich und daher immer aktiv.', + necessaryStatus: 'Immer aktiv', + analyticsTitle: 'Nutzungsstatistik (optional)', + analyticsBody: 'Nutzungsstatistiken, die uns helfen, den Dienst zu verbessern.', + analyticsSwitch: 'Nutzungsstatistik erlauben', + save: 'Auswahl speichern', + cancel: 'Abbrechen', + close: 'Schließen', + saved: 'Ihre Cookie-Einstellungen wurden gespeichert.', + trigger: 'Cookie-Einstellungen', + }), + es: Object.freeze({ + regionLabel: 'Consentimiento de cookies', + title: 'Estadísticas de uso (opcional)', + body: 'Recopilamos estadísticas de uso para mejorar el servicio. Es opcional, y todo funciona sin ello.', + learnMore: 'Más información', + privacyLink: 'Política de privacidad', + acceptAll: 'Aceptar todo', + rejectAll: 'Rechazar', + settings: 'Configuración', + dismiss: 'Cerrar sin elegir', + settingsTitle: 'Configuración de cookies', + settingsIntro: 'Puedes cambiarlo en cualquier momento en «Configuración de cookies», en el pie de página.', + necessaryTitle: 'Necesarias', + necessaryBody: 'Imprescindibles para que el sitio funcione, por eso siempre están activas.', + necessaryStatus: 'Siempre activas', + analyticsTitle: 'Estadísticas de uso (opcional)', + analyticsBody: 'Estadísticas de uso que nos ayudan a mejorar el servicio.', + analyticsSwitch: 'Permitir estadísticas de uso', + save: 'Guardar elección', + cancel: 'Cancelar', + close: 'Cerrar', + saved: 'Se ha guardado tu configuración de cookies.', + trigger: 'Configuración de cookies', + }), + ar: Object.freeze({ + regionLabel: 'الموافقة على ملفات تعريف الارتباط', + title: 'إحصاءات الاستخدام (اختيارية)', + body: 'نجمع إحصاءات الاستخدام لتحسين الخدمة. الموافقة اختيارية، ويعمل كل شيء بدونها.', + learnMore: 'اعرف المزيد', + privacyLink: 'سياسة الخصوصية', + acceptAll: 'قبول الكل', + rejectAll: 'رفض', + settings: 'الإعدادات', + dismiss: 'إغلاق دون اختيار', + settingsTitle: 'إعدادات ملفات تعريف الارتباط', + settingsIntro: 'يمكنك تغيير ذلك في أي وقت من «إعدادات ملفات تعريف الارتباط» في تذييل الصفحة.', + necessaryTitle: 'ضرورية', + necessaryBody: 'لازمة لعمل الموقع، لذلك تظل مفعّلة دائمًا.', + necessaryStatus: 'مفعّلة دائمًا', + analyticsTitle: 'إحصاءات الاستخدام (اختيارية)', + analyticsBody: 'إحصاءات استخدام تساعدنا على تحسين الخدمة.', + analyticsSwitch: 'السماح بإحصاءات الاستخدام', + save: 'حفظ الاختيارات', + cancel: 'إلغاء', + close: 'إغلاق', + saved: 'تم حفظ إعدادات ملفات تعريف الارتباط.', + trigger: 'إعدادات ملفات تعريف الارتباط', + }), +}); + +/** + * Strings for a document language: the exact tag, then its base language + * (zh falls to zh-TW only through an explicit tag — a bare `zh` reads + * English, as the site does not serve Simplified Chinese), else English. + * @param {string | null | undefined} lang + * @returns {{ lang: string, messages: Readonly }} + */ +export function consentMessagesFor(lang) { + const tag = typeof lang === 'string' ? lang.trim() : ''; + const exact = Object.keys(CONSENT_MESSAGES).find((key) => key.toLowerCase() === tag.toLowerCase()); + if (exact) return { lang: exact, messages: CONSENT_MESSAGES[exact] }; + const base = tag.split('-')[0].toLowerCase(); + if (base && base !== 'zh' && CONSENT_MESSAGES[base]) return { lang: base, messages: CONSENT_MESSAGES[base] }; + return { lang: 'en', messages: CONSENT_MESSAGES.en }; +} From 7967e1b25208c093cf560f4a36827bb55286ba2a Mon Sep 17 00:00:00 2001 From: Sin-Kang Date: Sat, 14 Nov 2026 14:14:46 +0900 Subject: [PATCH 2/3] chore: preserve repository LF line endings --- assets/consent/messages.js | 798 ++++++++++++++++++------------------- 1 file changed, 399 insertions(+), 399 deletions(-) diff --git a/assets/consent/messages.js b/assets/consent/messages.js index 64ad98b..62716c0 100644 --- a/assets/consent/messages.js +++ b/assets/consent/messages.js @@ -1,399 +1,399 @@ -/** - * Consent bar and settings strings, including Kannada. Shared by devslab.kr and - * the open-source hub (devslab-kr.github.io). - * - * Korean and English are @devslab/site-kit's CONSENT_MESSAGES_KO / _EN word - * for word (a test pins that); the other locales say the same short things in - * the same neutral tone (owner decision 2026-10-06, DDS D-034): what is - * collected and why, that it is optional, and a "learn more" link. The full - * disclosure — Google Analytics 4, Google LLC, the transfer to the United - * States, 14 months, no ads, how to withdraw — is not here: it lives in the - * privacy policy section the bar's learnMore link opens - * (devslab.kr/privacy#processors, which covers both sites). The settings - * intro names the footer control by that locale's own `trigger` label. - * - * Shared file: the hub vendors a byte-identical copy at - * assets/consent/messages.js. Change both together. - */ - -/** @typedef {Record<'regionLabel'|'title'|'body'|'learnMore'|'privacyLink'|'acceptAll'|'rejectAll'|'settings'|'dismiss'|'settingsTitle'|'settingsIntro'|'necessaryTitle'|'necessaryBody'|'necessaryStatus'|'analyticsTitle'|'analyticsBody'|'analyticsSwitch'|'save'|'cancel'|'close'|'saved'|'trigger', string>} ConsentMessages */ - -/** @type {Readonly>>} */ -export const CONSENT_MESSAGES = Object.freeze({ - ko: Object.freeze({ - regionLabel: '쿠키 동의', - title: '이용 통계 수집 동의 (선택)', - body: '서비스를 더 낫게 만들기 위해 이용 통계를 수집합니다. 동의는 선택이며, 동의하지 않아도 모든 기능을 쓸 수 있습니다.', - learnMore: '자세히 보기', - privacyLink: '개인정보처리방침', - acceptAll: '모두 허용', - rejectAll: '거부', - settings: '설정', - dismiss: '선택하지 않고 닫기', - settingsTitle: '쿠키 설정', - settingsIntro: '바닥글의 ‘쿠키 설정’에서 언제든 다시 바꿀 수 있습니다.', - necessaryTitle: '필수', - necessaryBody: '사이트가 동작하는 데 꼭 필요해 항상 사용합니다.', - necessaryStatus: '항상 사용', - analyticsTitle: '이용 통계 (선택)', - analyticsBody: '서비스를 개선하는 데 쓰는 이용 통계입니다.', - analyticsSwitch: '이용 통계 수집 허용', - save: '선택 저장', - cancel: '취소', - close: '닫기', - saved: '쿠키 설정을 저장했습니다.', - trigger: '쿠키 설정', - }), - en: Object.freeze({ - regionLabel: 'Cookie consent', - title: 'Analytics (optional)', - body: "We collect usage statistics to improve the service. It's optional, and everything works without it.", - learnMore: 'Learn more', - privacyLink: 'Privacy policy', - acceptAll: 'Accept all', - rejectAll: 'Reject', - settings: 'Settings', - dismiss: 'Close without choosing', - settingsTitle: 'Cookie settings', - settingsIntro: 'You can change this at any time under “Cookie settings” in the footer.', - necessaryTitle: 'Necessary', - necessaryBody: 'Needed for the site to work, so always on.', - necessaryStatus: 'Always on', - analyticsTitle: 'Analytics (optional)', - analyticsBody: 'Usage statistics that help us improve the service.', - analyticsSwitch: 'Allow analytics', - save: 'Save choices', - cancel: 'Cancel', - close: 'Close', - saved: 'Your cookie settings are saved.', - trigger: 'Cookie settings', - }), - ja: Object.freeze({ - regionLabel: 'Cookieの同意', - title: '利用統計の収集への同意(任意)', - body: 'サービスの改善のため、利用統計を収集します。同意は任意で、同意しなくてもすべての機能をご利用いただけます。', - learnMore: '詳しく見る', - privacyLink: 'プライバシーポリシー', - acceptAll: 'すべて許可', - rejectAll: '拒否', - settings: '設定', - dismiss: '選ばずに閉じる', - settingsTitle: 'Cookie設定', - settingsIntro: 'フッターの「Cookie設定」からいつでも変更できます。', - necessaryTitle: '必須', - necessaryBody: 'サイトの動作に欠かせないため、常に使用します。', - necessaryStatus: '常に使用', - analyticsTitle: '利用統計(任意)', - analyticsBody: 'サービスの改善に使う利用統計です。', - analyticsSwitch: '利用統計の収集を許可', - save: '選択を保存', - cancel: 'キャンセル', - close: '閉じる', - saved: 'Cookie設定を保存しました。', - trigger: 'Cookie設定', - }), - 'zh-HK': Object.freeze({ - regionLabel: 'Cookie 同意', - title: '同意收集使用統計(可選)', - body: '我們會收集使用統計,以改善服務。是否同意由你決定,即使不同意,所有功能仍可照常使用。', - learnMore: '了解更多', - privacyLink: '私隱政策', - acceptAll: '全部允許', - rejectAll: '拒絕', - settings: '設定', - dismiss: '不作選擇並關閉', - settingsTitle: 'Cookie 設定', - settingsIntro: '你可隨時在頁尾的「Cookie 設定」更改選擇。', - necessaryTitle: '必要', - necessaryBody: '網站運作所必需,因此一直使用。', - necessaryStatus: '一直使用', - analyticsTitle: '使用統計(可選)', - analyticsBody: '用於改善服務的使用統計。', - analyticsSwitch: '允許收集使用統計', - save: '儲存選擇', - cancel: '取消', - close: '關閉', - saved: '已儲存 Cookie 設定。', - trigger: 'Cookie 設定', - }), - 'zh-TW': Object.freeze({ - regionLabel: 'Cookie 同意', - title: '同意收集使用統計(選用)', - body: '我們會收集使用統計,以改善服務。是否同意由您決定,即使不同意,所有功能仍可正常使用。', - learnMore: '瞭解詳情', - privacyLink: '隱私權政策', - acceptAll: '全部允許', - rejectAll: '拒絕', - settings: '設定', - dismiss: '不選擇並關閉', - settingsTitle: 'Cookie 設定', - settingsIntro: '您可以隨時在頁尾的「Cookie 設定」變更選擇。', - necessaryTitle: '必要', - necessaryBody: '網站運作所必需,因此一律使用。', - necessaryStatus: '一律使用', - analyticsTitle: '使用統計(選用)', - analyticsBody: '用於改善服務的使用統計。', - analyticsSwitch: '允許收集使用統計', - save: '儲存選擇', - cancel: '取消', - close: '關閉', - saved: '已儲存 Cookie 設定。', - trigger: 'Cookie 設定', - }), - kn: Object.freeze({ - regionLabel: 'ಕುಕೀ ಸಮ್ಮತಿ', - title: 'ಬಳಕೆಯ ಅಂಕಿಅಂಶಗಳು (ಐಚ್ಛಿಕ)', - body: 'ಸೇವೆಯನ್ನು ಸುಧಾರಿಸಲು ಬಳಕೆಯ ಅಂಕಿಅಂಶಗಳನ್ನು ಸಂಗ್ರಹಿಸುತ್ತೇವೆ. ಇದು ಐಚ್ಛಿಕ. ಒಪ್ಪದಿದ್ದರೂ ಎಲ್ಲ ಸೌಲಭ್ಯಗಳನ್ನು ಬಳಸಬಹುದು.', - learnMore: 'ಇನ್ನಷ್ಟು ತಿಳಿಯಿರಿ', - privacyLink: 'ಗೌಪ್ಯತಾ ನೀತಿ', - acceptAll: 'ಎಲ್ಲವನ್ನೂ ಒಪ್ಪಿ', - rejectAll: 'ನಿರಾಕರಿಸಿ', - settings: 'ಸೆಟ್ಟಿಂಗ್‌ಗಳು', - dismiss: 'ಆಯ್ಕೆ ಮಾಡದೆ ಮುಚ್ಚಿ', - settingsTitle: 'ಕುಕೀ ಸೆಟ್ಟಿಂಗ್‌ಗಳು', - settingsIntro: 'ಪುಟದ ಕೆಳಗಿನ “ಕುಕೀ ಸೆಟ್ಟಿಂಗ್‌ಗಳು” ಮೂಲಕ ಯಾವಾಗ ಬೇಕಾದರೂ ಬದಲಾಯಿಸಬಹುದು.', - necessaryTitle: 'ಅಗತ್ಯ', - necessaryBody: 'ಸೈಟ್ ಕಾರ್ಯನಿರ್ವಹಿಸಲು ಅಗತ್ಯವಾದ್ದರಿಂದ ಯಾವಾಗಲೂ ಸಕ್ರಿಯವಾಗಿರುತ್ತವೆ.', - necessaryStatus: 'ಯಾವಾಗಲೂ ಸಕ್ರಿಯ', - analyticsTitle: 'ಬಳಕೆಯ ಅಂಕಿಅಂಶಗಳು (ಐಚ್ಛಿಕ)', - analyticsBody: 'ಸೇವೆಯನ್ನು ಸುಧಾರಿಸಲು ನೆರವಾಗುವ ಬಳಕೆಯ ಅಂಕಿಅಂಶಗಳು.', - analyticsSwitch: 'ಬಳಕೆಯ ಅಂಕಿಅಂಶ ಸಂಗ್ರಹಕ್ಕೆ ಅನುಮತಿಸಿ', - save: 'ಆಯ್ಕೆಗಳನ್ನು ಉಳಿಸಿ', - cancel: 'ರದ್ದುಮಾಡಿ', - close: 'ಮುಚ್ಚಿ', - saved: 'ಕುಕೀ ಸೆಟ್ಟಿಂಗ್‌ಗಳನ್ನು ಉಳಿಸಲಾಗಿದೆ.', - trigger: 'ಕುಕೀ ಸೆಟ್ಟಿಂಗ್‌ಗಳು', - }), - hi: Object.freeze({ - regionLabel: 'कुकी सहमति', - title: 'उपयोग के आँकड़े (वैकल्पिक)', - body: 'सेवा को बेहतर बनाने के लिए हम उपयोग के आँकड़े इकट्ठा करते हैं। यह वैकल्पिक है, और इसके बिना भी सब कुछ काम करता है।', - learnMore: 'और जानें', - privacyLink: 'गोपनीयता नीति', - acceptAll: 'सभी स्वीकार करें', - rejectAll: 'अस्वीकार करें', - settings: 'सेटिंग', - dismiss: 'बिना चुने बंद करें', - settingsTitle: 'कुकी सेटिंग', - settingsIntro: 'आप फ़ुटर में “कुकी सेटिंग” से इसे कभी भी बदल सकते हैं।', - necessaryTitle: 'आवश्यक', - necessaryBody: 'साइट के काम करने के लिए ज़रूरी हैं, इसलिए हमेशा चालू रहती हैं।', - necessaryStatus: 'हमेशा चालू', - analyticsTitle: 'उपयोग के आँकड़े (वैकल्पिक)', - analyticsBody: 'उपयोग के आँकड़े, जिनसे हमें सेवा बेहतर बनाने में मदद मिलती है।', - analyticsSwitch: 'उपयोग के आँकड़ों की अनुमति दें', - save: 'चुनाव सहेजें', - cancel: 'रद्द करें', - close: 'बंद करें', - saved: 'आपकी कुकी सेटिंग सहेज ली गई है।', - trigger: 'कुकी सेटिंग', - }), - vi: Object.freeze({ - regionLabel: 'Đồng ý cookie', - title: 'Thống kê sử dụng (tùy chọn)', - body: 'Chúng tôi thu thập số liệu thống kê sử dụng để cải thiện dịch vụ. Việc này là tùy chọn, và mọi tính năng vẫn hoạt động khi bạn không đồng ý.', - learnMore: 'Tìm hiểu thêm', - privacyLink: 'Chính sách quyền riêng tư', - acceptAll: 'Chấp nhận tất cả', - rejectAll: 'Từ chối', - settings: 'Cài đặt', - dismiss: 'Đóng mà không chọn', - settingsTitle: 'Cài đặt cookie', - settingsIntro: 'Bạn có thể thay đổi lựa chọn bất cứ lúc nào tại “Cài đặt cookie” ở chân trang.', - necessaryTitle: 'Cần thiết', - necessaryBody: 'Cần để trang hoạt động, nên luôn được bật.', - necessaryStatus: 'Luôn bật', - analyticsTitle: 'Thống kê sử dụng (tùy chọn)', - analyticsBody: 'Số liệu thống kê sử dụng giúp chúng tôi cải thiện dịch vụ.', - analyticsSwitch: 'Cho phép thống kê sử dụng', - save: 'Lưu lựa chọn', - cancel: 'Hủy', - close: 'Đóng', - saved: 'Đã lưu cài đặt cookie của bạn.', - trigger: 'Cài đặt cookie', - }), - id: Object.freeze({ - regionLabel: 'Persetujuan cookie', - title: 'Statistik penggunaan (opsional)', - body: 'Kami mengumpulkan statistik penggunaan untuk meningkatkan layanan. Ini opsional, dan semua fitur tetap berfungsi tanpanya.', - learnMore: 'Pelajari lebih lanjut', - privacyLink: 'Kebijakan Privasi', - acceptAll: 'Terima semua', - rejectAll: 'Tolak', - settings: 'Pengaturan', - dismiss: 'Tutup tanpa memilih', - settingsTitle: 'Pengaturan cookie', - settingsIntro: 'Anda dapat mengubahnya kapan saja melalui “Pengaturan cookie” di footer.', - necessaryTitle: 'Diperlukan', - necessaryBody: 'Dibutuhkan agar situs berfungsi, jadi selalu aktif.', - necessaryStatus: 'Selalu aktif', - analyticsTitle: 'Statistik penggunaan (opsional)', - analyticsBody: 'Statistik penggunaan yang membantu kami meningkatkan layanan.', - analyticsSwitch: 'Izinkan statistik penggunaan', - save: 'Simpan pilihan', - cancel: 'Batal', - close: 'Tutup', - saved: 'Pengaturan cookie Anda telah disimpan.', - trigger: 'Pengaturan cookie', - }), - th: Object.freeze({ - regionLabel: 'ความยินยอมคุกกี้', - title: 'สถิติการใช้งาน (ไม่บังคับ)', - body: 'เราเก็บสถิติการใช้งานเพื่อปรับปรุงบริการ การยินยอมเป็นทางเลือก และทุกฟังก์ชันใช้งานได้แม้ไม่ยินยอม', - learnMore: 'ดูรายละเอียด', - privacyLink: 'นโยบายความเป็นส่วนตัว', - acceptAll: 'ยอมรับทั้งหมด', - rejectAll: 'ปฏิเสธ', - settings: 'ตั้งค่า', - dismiss: 'ปิดโดยไม่เลือก', - settingsTitle: 'การตั้งค่าคุกกี้', - settingsIntro: 'คุณเปลี่ยนตัวเลือกได้ทุกเมื่อที่ “การตั้งค่าคุกกี้” ในส่วนท้ายของหน้า', - necessaryTitle: 'จำเป็น', - necessaryBody: 'จำเป็นต่อการทำงานของเว็บไซต์ จึงเปิดใช้เสมอ', - necessaryStatus: 'เปิดใช้เสมอ', - analyticsTitle: 'สถิติการใช้งาน (ไม่บังคับ)', - analyticsBody: 'สถิติการใช้งานที่ช่วยให้เราปรับปรุงบริการ', - analyticsSwitch: 'อนุญาตสถิติการใช้งาน', - save: 'บันทึกตัวเลือก', - cancel: 'ยกเลิก', - close: 'ปิด', - saved: 'บันทึกการตั้งค่าคุกกี้แล้ว', - trigger: 'การตั้งค่าคุกกี้', - }), - 'pt-BR': Object.freeze({ - regionLabel: 'Consentimento de cookies', - title: 'Estatísticas de uso (opcional)', - body: 'Coletamos estatísticas de uso para melhorar o serviço. É opcional, e tudo funciona sem isso.', - learnMore: 'Saiba mais', - privacyLink: 'Política de Privacidade', - acceptAll: 'Aceitar todos', - rejectAll: 'Recusar', - settings: 'Configurações', - dismiss: 'Fechar sem escolher', - settingsTitle: 'Configurações de cookies', - settingsIntro: 'Você pode mudar isso a qualquer momento em “Configurações de cookies”, no rodapé.', - necessaryTitle: 'Necessários', - necessaryBody: 'Necessários para o site funcionar, por isso estão sempre ativos.', - necessaryStatus: 'Sempre ativos', - analyticsTitle: 'Estatísticas de uso (opcional)', - analyticsBody: 'Estatísticas de uso que nos ajudam a melhorar o serviço.', - analyticsSwitch: 'Permitir estatísticas de uso', - save: 'Salvar escolhas', - cancel: 'Cancelar', - close: 'Fechar', - saved: 'Suas configurações de cookies foram salvas.', - trigger: 'Configurações de cookies', - }), - fr: Object.freeze({ - regionLabel: 'Consentement aux cookies', - title: 'Mesure d’audience (facultatif)', - body: 'Nous recueillons des statistiques d’utilisation pour améliorer le service. C’est facultatif, et tout fonctionne sans.', - learnMore: 'En savoir plus', - privacyLink: 'Politique de confidentialité', - acceptAll: 'Tout accepter', - rejectAll: 'Refuser', - settings: 'Paramètres', - dismiss: 'Fermer sans choisir', - settingsTitle: 'Paramètres des cookies', - settingsIntro: 'Vous pouvez modifier ce choix à tout moment via « Paramètres des cookies » en bas de page.', - necessaryTitle: 'Nécessaires', - necessaryBody: 'Indispensables au fonctionnement du site, donc toujours actifs.', - necessaryStatus: 'Toujours actifs', - analyticsTitle: 'Mesure d’audience (facultatif)', - analyticsBody: 'Des statistiques d’utilisation qui nous aident à améliorer le service.', - analyticsSwitch: 'Autoriser la mesure d’audience', - save: 'Enregistrer mes choix', - cancel: 'Annuler', - close: 'Fermer', - saved: 'Vos paramètres de cookies sont enregistrés.', - trigger: 'Paramètres des cookies', - }), - de: Object.freeze({ - regionLabel: 'Cookie-Einwilligung', - title: 'Nutzungsstatistik (optional)', - body: 'Wir erfassen Nutzungsstatistiken, um den Dienst zu verbessern. Das ist freiwillig, und alles funktioniert auch ohne.', - learnMore: 'Mehr erfahren', - privacyLink: 'Datenschutzerklärung', - acceptAll: 'Alle akzeptieren', - rejectAll: 'Ablehnen', - settings: 'Einstellungen', - dismiss: 'Ohne Auswahl schließen', - settingsTitle: 'Cookie-Einstellungen', - settingsIntro: 'Unter „Cookie-Einstellungen“ in der Fußzeile können Sie das jederzeit ändern.', - necessaryTitle: 'Notwendig', - necessaryBody: 'Für den Betrieb der Website erforderlich und daher immer aktiv.', - necessaryStatus: 'Immer aktiv', - analyticsTitle: 'Nutzungsstatistik (optional)', - analyticsBody: 'Nutzungsstatistiken, die uns helfen, den Dienst zu verbessern.', - analyticsSwitch: 'Nutzungsstatistik erlauben', - save: 'Auswahl speichern', - cancel: 'Abbrechen', - close: 'Schließen', - saved: 'Ihre Cookie-Einstellungen wurden gespeichert.', - trigger: 'Cookie-Einstellungen', - }), - es: Object.freeze({ - regionLabel: 'Consentimiento de cookies', - title: 'Estadísticas de uso (opcional)', - body: 'Recopilamos estadísticas de uso para mejorar el servicio. Es opcional, y todo funciona sin ello.', - learnMore: 'Más información', - privacyLink: 'Política de privacidad', - acceptAll: 'Aceptar todo', - rejectAll: 'Rechazar', - settings: 'Configuración', - dismiss: 'Cerrar sin elegir', - settingsTitle: 'Configuración de cookies', - settingsIntro: 'Puedes cambiarlo en cualquier momento en «Configuración de cookies», en el pie de página.', - necessaryTitle: 'Necesarias', - necessaryBody: 'Imprescindibles para que el sitio funcione, por eso siempre están activas.', - necessaryStatus: 'Siempre activas', - analyticsTitle: 'Estadísticas de uso (opcional)', - analyticsBody: 'Estadísticas de uso que nos ayudan a mejorar el servicio.', - analyticsSwitch: 'Permitir estadísticas de uso', - save: 'Guardar elección', - cancel: 'Cancelar', - close: 'Cerrar', - saved: 'Se ha guardado tu configuración de cookies.', - trigger: 'Configuración de cookies', - }), - ar: Object.freeze({ - regionLabel: 'الموافقة على ملفات تعريف الارتباط', - title: 'إحصاءات الاستخدام (اختيارية)', - body: 'نجمع إحصاءات الاستخدام لتحسين الخدمة. الموافقة اختيارية، ويعمل كل شيء بدونها.', - learnMore: 'اعرف المزيد', - privacyLink: 'سياسة الخصوصية', - acceptAll: 'قبول الكل', - rejectAll: 'رفض', - settings: 'الإعدادات', - dismiss: 'إغلاق دون اختيار', - settingsTitle: 'إعدادات ملفات تعريف الارتباط', - settingsIntro: 'يمكنك تغيير ذلك في أي وقت من «إعدادات ملفات تعريف الارتباط» في تذييل الصفحة.', - necessaryTitle: 'ضرورية', - necessaryBody: 'لازمة لعمل الموقع، لذلك تظل مفعّلة دائمًا.', - necessaryStatus: 'مفعّلة دائمًا', - analyticsTitle: 'إحصاءات الاستخدام (اختيارية)', - analyticsBody: 'إحصاءات استخدام تساعدنا على تحسين الخدمة.', - analyticsSwitch: 'السماح بإحصاءات الاستخدام', - save: 'حفظ الاختيارات', - cancel: 'إلغاء', - close: 'إغلاق', - saved: 'تم حفظ إعدادات ملفات تعريف الارتباط.', - trigger: 'إعدادات ملفات تعريف الارتباط', - }), -}); - -/** - * Strings for a document language: the exact tag, then its base language - * (zh falls to zh-TW only through an explicit tag — a bare `zh` reads - * English, as the site does not serve Simplified Chinese), else English. - * @param {string | null | undefined} lang - * @returns {{ lang: string, messages: Readonly }} - */ -export function consentMessagesFor(lang) { - const tag = typeof lang === 'string' ? lang.trim() : ''; - const exact = Object.keys(CONSENT_MESSAGES).find((key) => key.toLowerCase() === tag.toLowerCase()); - if (exact) return { lang: exact, messages: CONSENT_MESSAGES[exact] }; - const base = tag.split('-')[0].toLowerCase(); - if (base && base !== 'zh' && CONSENT_MESSAGES[base]) return { lang: base, messages: CONSENT_MESSAGES[base] }; - return { lang: 'en', messages: CONSENT_MESSAGES.en }; -} +/** + * Consent bar and settings strings, including Kannada. Shared by devslab.kr and + * the open-source hub (devslab-kr.github.io). + * + * Korean and English are @devslab/site-kit's CONSENT_MESSAGES_KO / _EN word + * for word (a test pins that); the other locales say the same short things in + * the same neutral tone (owner decision 2026-10-06, DDS D-034): what is + * collected and why, that it is optional, and a "learn more" link. The full + * disclosure — Google Analytics 4, Google LLC, the transfer to the United + * States, 14 months, no ads, how to withdraw — is not here: it lives in the + * privacy policy section the bar's learnMore link opens + * (devslab.kr/privacy#processors, which covers both sites). The settings + * intro names the footer control by that locale's own `trigger` label. + * + * Shared file: the hub vendors a byte-identical copy at + * assets/consent/messages.js. Change both together. + */ + +/** @typedef {Record<'regionLabel'|'title'|'body'|'learnMore'|'privacyLink'|'acceptAll'|'rejectAll'|'settings'|'dismiss'|'settingsTitle'|'settingsIntro'|'necessaryTitle'|'necessaryBody'|'necessaryStatus'|'analyticsTitle'|'analyticsBody'|'analyticsSwitch'|'save'|'cancel'|'close'|'saved'|'trigger', string>} ConsentMessages */ + +/** @type {Readonly>>} */ +export const CONSENT_MESSAGES = Object.freeze({ + ko: Object.freeze({ + regionLabel: '쿠키 동의', + title: '이용 통계 수집 동의 (선택)', + body: '서비스를 더 낫게 만들기 위해 이용 통계를 수집합니다. 동의는 선택이며, 동의하지 않아도 모든 기능을 쓸 수 있습니다.', + learnMore: '자세히 보기', + privacyLink: '개인정보처리방침', + acceptAll: '모두 허용', + rejectAll: '거부', + settings: '설정', + dismiss: '선택하지 않고 닫기', + settingsTitle: '쿠키 설정', + settingsIntro: '바닥글의 ‘쿠키 설정’에서 언제든 다시 바꿀 수 있습니다.', + necessaryTitle: '필수', + necessaryBody: '사이트가 동작하는 데 꼭 필요해 항상 사용합니다.', + necessaryStatus: '항상 사용', + analyticsTitle: '이용 통계 (선택)', + analyticsBody: '서비스를 개선하는 데 쓰는 이용 통계입니다.', + analyticsSwitch: '이용 통계 수집 허용', + save: '선택 저장', + cancel: '취소', + close: '닫기', + saved: '쿠키 설정을 저장했습니다.', + trigger: '쿠키 설정', + }), + en: Object.freeze({ + regionLabel: 'Cookie consent', + title: 'Analytics (optional)', + body: "We collect usage statistics to improve the service. It's optional, and everything works without it.", + learnMore: 'Learn more', + privacyLink: 'Privacy policy', + acceptAll: 'Accept all', + rejectAll: 'Reject', + settings: 'Settings', + dismiss: 'Close without choosing', + settingsTitle: 'Cookie settings', + settingsIntro: 'You can change this at any time under “Cookie settings” in the footer.', + necessaryTitle: 'Necessary', + necessaryBody: 'Needed for the site to work, so always on.', + necessaryStatus: 'Always on', + analyticsTitle: 'Analytics (optional)', + analyticsBody: 'Usage statistics that help us improve the service.', + analyticsSwitch: 'Allow analytics', + save: 'Save choices', + cancel: 'Cancel', + close: 'Close', + saved: 'Your cookie settings are saved.', + trigger: 'Cookie settings', + }), + ja: Object.freeze({ + regionLabel: 'Cookieの同意', + title: '利用統計の収集への同意(任意)', + body: 'サービスの改善のため、利用統計を収集します。同意は任意で、同意しなくてもすべての機能をご利用いただけます。', + learnMore: '詳しく見る', + privacyLink: 'プライバシーポリシー', + acceptAll: 'すべて許可', + rejectAll: '拒否', + settings: '設定', + dismiss: '選ばずに閉じる', + settingsTitle: 'Cookie設定', + settingsIntro: 'フッターの「Cookie設定」からいつでも変更できます。', + necessaryTitle: '必須', + necessaryBody: 'サイトの動作に欠かせないため、常に使用します。', + necessaryStatus: '常に使用', + analyticsTitle: '利用統計(任意)', + analyticsBody: 'サービスの改善に使う利用統計です。', + analyticsSwitch: '利用統計の収集を許可', + save: '選択を保存', + cancel: 'キャンセル', + close: '閉じる', + saved: 'Cookie設定を保存しました。', + trigger: 'Cookie設定', + }), + 'zh-HK': Object.freeze({ + regionLabel: 'Cookie 同意', + title: '同意收集使用統計(可選)', + body: '我們會收集使用統計,以改善服務。是否同意由你決定,即使不同意,所有功能仍可照常使用。', + learnMore: '了解更多', + privacyLink: '私隱政策', + acceptAll: '全部允許', + rejectAll: '拒絕', + settings: '設定', + dismiss: '不作選擇並關閉', + settingsTitle: 'Cookie 設定', + settingsIntro: '你可隨時在頁尾的「Cookie 設定」更改選擇。', + necessaryTitle: '必要', + necessaryBody: '網站運作所必需,因此一直使用。', + necessaryStatus: '一直使用', + analyticsTitle: '使用統計(可選)', + analyticsBody: '用於改善服務的使用統計。', + analyticsSwitch: '允許收集使用統計', + save: '儲存選擇', + cancel: '取消', + close: '關閉', + saved: '已儲存 Cookie 設定。', + trigger: 'Cookie 設定', + }), + 'zh-TW': Object.freeze({ + regionLabel: 'Cookie 同意', + title: '同意收集使用統計(選用)', + body: '我們會收集使用統計,以改善服務。是否同意由您決定,即使不同意,所有功能仍可正常使用。', + learnMore: '瞭解詳情', + privacyLink: '隱私權政策', + acceptAll: '全部允許', + rejectAll: '拒絕', + settings: '設定', + dismiss: '不選擇並關閉', + settingsTitle: 'Cookie 設定', + settingsIntro: '您可以隨時在頁尾的「Cookie 設定」變更選擇。', + necessaryTitle: '必要', + necessaryBody: '網站運作所必需,因此一律使用。', + necessaryStatus: '一律使用', + analyticsTitle: '使用統計(選用)', + analyticsBody: '用於改善服務的使用統計。', + analyticsSwitch: '允許收集使用統計', + save: '儲存選擇', + cancel: '取消', + close: '關閉', + saved: '已儲存 Cookie 設定。', + trigger: 'Cookie 設定', + }), + kn: Object.freeze({ + regionLabel: 'ಕುಕೀ ಸಮ್ಮತಿ', + title: 'ಬಳಕೆಯ ಅಂಕಿಅಂಶಗಳು (ಐಚ್ಛಿಕ)', + body: 'ಸೇವೆಯನ್ನು ಸುಧಾರಿಸಲು ಬಳಕೆಯ ಅಂಕಿಅಂಶಗಳನ್ನು ಸಂಗ್ರಹಿಸುತ್ತೇವೆ. ಇದು ಐಚ್ಛಿಕ. ಒಪ್ಪದಿದ್ದರೂ ಎಲ್ಲ ಸೌಲಭ್ಯಗಳನ್ನು ಬಳಸಬಹುದು.', + learnMore: 'ಇನ್ನಷ್ಟು ತಿಳಿಯಿರಿ', + privacyLink: 'ಗೌಪ್ಯತಾ ನೀತಿ', + acceptAll: 'ಎಲ್ಲವನ್ನೂ ಒಪ್ಪಿ', + rejectAll: 'ನಿರಾಕರಿಸಿ', + settings: 'ಸೆಟ್ಟಿಂಗ್‌ಗಳು', + dismiss: 'ಆಯ್ಕೆ ಮಾಡದೆ ಮುಚ್ಚಿ', + settingsTitle: 'ಕುಕೀ ಸೆಟ್ಟಿಂಗ್‌ಗಳು', + settingsIntro: 'ಪುಟದ ಕೆಳಗಿನ “ಕುಕೀ ಸೆಟ್ಟಿಂಗ್‌ಗಳು” ಮೂಲಕ ಯಾವಾಗ ಬೇಕಾದರೂ ಬದಲಾಯಿಸಬಹುದು.', + necessaryTitle: 'ಅಗತ್ಯ', + necessaryBody: 'ಸೈಟ್ ಕಾರ್ಯನಿರ್ವಹಿಸಲು ಅಗತ್ಯವಾದ್ದರಿಂದ ಯಾವಾಗಲೂ ಸಕ್ರಿಯವಾಗಿರುತ್ತವೆ.', + necessaryStatus: 'ಯಾವಾಗಲೂ ಸಕ್ರಿಯ', + analyticsTitle: 'ಬಳಕೆಯ ಅಂಕಿಅಂಶಗಳು (ಐಚ್ಛಿಕ)', + analyticsBody: 'ಸೇವೆಯನ್ನು ಸುಧಾರಿಸಲು ನೆರವಾಗುವ ಬಳಕೆಯ ಅಂಕಿಅಂಶಗಳು.', + analyticsSwitch: 'ಬಳಕೆಯ ಅಂಕಿಅಂಶ ಸಂಗ್ರಹಕ್ಕೆ ಅನುಮತಿಸಿ', + save: 'ಆಯ್ಕೆಗಳನ್ನು ಉಳಿಸಿ', + cancel: 'ರದ್ದುಮಾಡಿ', + close: 'ಮುಚ್ಚಿ', + saved: 'ಕುಕೀ ಸೆಟ್ಟಿಂಗ್‌ಗಳನ್ನು ಉಳಿಸಲಾಗಿದೆ.', + trigger: 'ಕುಕೀ ಸೆಟ್ಟಿಂಗ್‌ಗಳು', + }), + hi: Object.freeze({ + regionLabel: 'कुकी सहमति', + title: 'उपयोग के आँकड़े (वैकल्पिक)', + body: 'सेवा को बेहतर बनाने के लिए हम उपयोग के आँकड़े इकट्ठा करते हैं। यह वैकल्पिक है, और इसके बिना भी सब कुछ काम करता है।', + learnMore: 'और जानें', + privacyLink: 'गोपनीयता नीति', + acceptAll: 'सभी स्वीकार करें', + rejectAll: 'अस्वीकार करें', + settings: 'सेटिंग', + dismiss: 'बिना चुने बंद करें', + settingsTitle: 'कुकी सेटिंग', + settingsIntro: 'आप फ़ुटर में “कुकी सेटिंग” से इसे कभी भी बदल सकते हैं।', + necessaryTitle: 'आवश्यक', + necessaryBody: 'साइट के काम करने के लिए ज़रूरी हैं, इसलिए हमेशा चालू रहती हैं।', + necessaryStatus: 'हमेशा चालू', + analyticsTitle: 'उपयोग के आँकड़े (वैकल्पिक)', + analyticsBody: 'उपयोग के आँकड़े, जिनसे हमें सेवा बेहतर बनाने में मदद मिलती है।', + analyticsSwitch: 'उपयोग के आँकड़ों की अनुमति दें', + save: 'चुनाव सहेजें', + cancel: 'रद्द करें', + close: 'बंद करें', + saved: 'आपकी कुकी सेटिंग सहेज ली गई है।', + trigger: 'कुकी सेटिंग', + }), + vi: Object.freeze({ + regionLabel: 'Đồng ý cookie', + title: 'Thống kê sử dụng (tùy chọn)', + body: 'Chúng tôi thu thập số liệu thống kê sử dụng để cải thiện dịch vụ. Việc này là tùy chọn, và mọi tính năng vẫn hoạt động khi bạn không đồng ý.', + learnMore: 'Tìm hiểu thêm', + privacyLink: 'Chính sách quyền riêng tư', + acceptAll: 'Chấp nhận tất cả', + rejectAll: 'Từ chối', + settings: 'Cài đặt', + dismiss: 'Đóng mà không chọn', + settingsTitle: 'Cài đặt cookie', + settingsIntro: 'Bạn có thể thay đổi lựa chọn bất cứ lúc nào tại “Cài đặt cookie” ở chân trang.', + necessaryTitle: 'Cần thiết', + necessaryBody: 'Cần để trang hoạt động, nên luôn được bật.', + necessaryStatus: 'Luôn bật', + analyticsTitle: 'Thống kê sử dụng (tùy chọn)', + analyticsBody: 'Số liệu thống kê sử dụng giúp chúng tôi cải thiện dịch vụ.', + analyticsSwitch: 'Cho phép thống kê sử dụng', + save: 'Lưu lựa chọn', + cancel: 'Hủy', + close: 'Đóng', + saved: 'Đã lưu cài đặt cookie của bạn.', + trigger: 'Cài đặt cookie', + }), + id: Object.freeze({ + regionLabel: 'Persetujuan cookie', + title: 'Statistik penggunaan (opsional)', + body: 'Kami mengumpulkan statistik penggunaan untuk meningkatkan layanan. Ini opsional, dan semua fitur tetap berfungsi tanpanya.', + learnMore: 'Pelajari lebih lanjut', + privacyLink: 'Kebijakan Privasi', + acceptAll: 'Terima semua', + rejectAll: 'Tolak', + settings: 'Pengaturan', + dismiss: 'Tutup tanpa memilih', + settingsTitle: 'Pengaturan cookie', + settingsIntro: 'Anda dapat mengubahnya kapan saja melalui “Pengaturan cookie” di footer.', + necessaryTitle: 'Diperlukan', + necessaryBody: 'Dibutuhkan agar situs berfungsi, jadi selalu aktif.', + necessaryStatus: 'Selalu aktif', + analyticsTitle: 'Statistik penggunaan (opsional)', + analyticsBody: 'Statistik penggunaan yang membantu kami meningkatkan layanan.', + analyticsSwitch: 'Izinkan statistik penggunaan', + save: 'Simpan pilihan', + cancel: 'Batal', + close: 'Tutup', + saved: 'Pengaturan cookie Anda telah disimpan.', + trigger: 'Pengaturan cookie', + }), + th: Object.freeze({ + regionLabel: 'ความยินยอมคุกกี้', + title: 'สถิติการใช้งาน (ไม่บังคับ)', + body: 'เราเก็บสถิติการใช้งานเพื่อปรับปรุงบริการ การยินยอมเป็นทางเลือก และทุกฟังก์ชันใช้งานได้แม้ไม่ยินยอม', + learnMore: 'ดูรายละเอียด', + privacyLink: 'นโยบายความเป็นส่วนตัว', + acceptAll: 'ยอมรับทั้งหมด', + rejectAll: 'ปฏิเสธ', + settings: 'ตั้งค่า', + dismiss: 'ปิดโดยไม่เลือก', + settingsTitle: 'การตั้งค่าคุกกี้', + settingsIntro: 'คุณเปลี่ยนตัวเลือกได้ทุกเมื่อที่ “การตั้งค่าคุกกี้” ในส่วนท้ายของหน้า', + necessaryTitle: 'จำเป็น', + necessaryBody: 'จำเป็นต่อการทำงานของเว็บไซต์ จึงเปิดใช้เสมอ', + necessaryStatus: 'เปิดใช้เสมอ', + analyticsTitle: 'สถิติการใช้งาน (ไม่บังคับ)', + analyticsBody: 'สถิติการใช้งานที่ช่วยให้เราปรับปรุงบริการ', + analyticsSwitch: 'อนุญาตสถิติการใช้งาน', + save: 'บันทึกตัวเลือก', + cancel: 'ยกเลิก', + close: 'ปิด', + saved: 'บันทึกการตั้งค่าคุกกี้แล้ว', + trigger: 'การตั้งค่าคุกกี้', + }), + 'pt-BR': Object.freeze({ + regionLabel: 'Consentimento de cookies', + title: 'Estatísticas de uso (opcional)', + body: 'Coletamos estatísticas de uso para melhorar o serviço. É opcional, e tudo funciona sem isso.', + learnMore: 'Saiba mais', + privacyLink: 'Política de Privacidade', + acceptAll: 'Aceitar todos', + rejectAll: 'Recusar', + settings: 'Configurações', + dismiss: 'Fechar sem escolher', + settingsTitle: 'Configurações de cookies', + settingsIntro: 'Você pode mudar isso a qualquer momento em “Configurações de cookies”, no rodapé.', + necessaryTitle: 'Necessários', + necessaryBody: 'Necessários para o site funcionar, por isso estão sempre ativos.', + necessaryStatus: 'Sempre ativos', + analyticsTitle: 'Estatísticas de uso (opcional)', + analyticsBody: 'Estatísticas de uso que nos ajudam a melhorar o serviço.', + analyticsSwitch: 'Permitir estatísticas de uso', + save: 'Salvar escolhas', + cancel: 'Cancelar', + close: 'Fechar', + saved: 'Suas configurações de cookies foram salvas.', + trigger: 'Configurações de cookies', + }), + fr: Object.freeze({ + regionLabel: 'Consentement aux cookies', + title: 'Mesure d’audience (facultatif)', + body: 'Nous recueillons des statistiques d’utilisation pour améliorer le service. C’est facultatif, et tout fonctionne sans.', + learnMore: 'En savoir plus', + privacyLink: 'Politique de confidentialité', + acceptAll: 'Tout accepter', + rejectAll: 'Refuser', + settings: 'Paramètres', + dismiss: 'Fermer sans choisir', + settingsTitle: 'Paramètres des cookies', + settingsIntro: 'Vous pouvez modifier ce choix à tout moment via « Paramètres des cookies » en bas de page.', + necessaryTitle: 'Nécessaires', + necessaryBody: 'Indispensables au fonctionnement du site, donc toujours actifs.', + necessaryStatus: 'Toujours actifs', + analyticsTitle: 'Mesure d’audience (facultatif)', + analyticsBody: 'Des statistiques d’utilisation qui nous aident à améliorer le service.', + analyticsSwitch: 'Autoriser la mesure d’audience', + save: 'Enregistrer mes choix', + cancel: 'Annuler', + close: 'Fermer', + saved: 'Vos paramètres de cookies sont enregistrés.', + trigger: 'Paramètres des cookies', + }), + de: Object.freeze({ + regionLabel: 'Cookie-Einwilligung', + title: 'Nutzungsstatistik (optional)', + body: 'Wir erfassen Nutzungsstatistiken, um den Dienst zu verbessern. Das ist freiwillig, und alles funktioniert auch ohne.', + learnMore: 'Mehr erfahren', + privacyLink: 'Datenschutzerklärung', + acceptAll: 'Alle akzeptieren', + rejectAll: 'Ablehnen', + settings: 'Einstellungen', + dismiss: 'Ohne Auswahl schließen', + settingsTitle: 'Cookie-Einstellungen', + settingsIntro: 'Unter „Cookie-Einstellungen“ in der Fußzeile können Sie das jederzeit ändern.', + necessaryTitle: 'Notwendig', + necessaryBody: 'Für den Betrieb der Website erforderlich und daher immer aktiv.', + necessaryStatus: 'Immer aktiv', + analyticsTitle: 'Nutzungsstatistik (optional)', + analyticsBody: 'Nutzungsstatistiken, die uns helfen, den Dienst zu verbessern.', + analyticsSwitch: 'Nutzungsstatistik erlauben', + save: 'Auswahl speichern', + cancel: 'Abbrechen', + close: 'Schließen', + saved: 'Ihre Cookie-Einstellungen wurden gespeichert.', + trigger: 'Cookie-Einstellungen', + }), + es: Object.freeze({ + regionLabel: 'Consentimiento de cookies', + title: 'Estadísticas de uso (opcional)', + body: 'Recopilamos estadísticas de uso para mejorar el servicio. Es opcional, y todo funciona sin ello.', + learnMore: 'Más información', + privacyLink: 'Política de privacidad', + acceptAll: 'Aceptar todo', + rejectAll: 'Rechazar', + settings: 'Configuración', + dismiss: 'Cerrar sin elegir', + settingsTitle: 'Configuración de cookies', + settingsIntro: 'Puedes cambiarlo en cualquier momento en «Configuración de cookies», en el pie de página.', + necessaryTitle: 'Necesarias', + necessaryBody: 'Imprescindibles para que el sitio funcione, por eso siempre están activas.', + necessaryStatus: 'Siempre activas', + analyticsTitle: 'Estadísticas de uso (opcional)', + analyticsBody: 'Estadísticas de uso que nos ayudan a mejorar el servicio.', + analyticsSwitch: 'Permitir estadísticas de uso', + save: 'Guardar elección', + cancel: 'Cancelar', + close: 'Cerrar', + saved: 'Se ha guardado tu configuración de cookies.', + trigger: 'Configuración de cookies', + }), + ar: Object.freeze({ + regionLabel: 'الموافقة على ملفات تعريف الارتباط', + title: 'إحصاءات الاستخدام (اختيارية)', + body: 'نجمع إحصاءات الاستخدام لتحسين الخدمة. الموافقة اختيارية، ويعمل كل شيء بدونها.', + learnMore: 'اعرف المزيد', + privacyLink: 'سياسة الخصوصية', + acceptAll: 'قبول الكل', + rejectAll: 'رفض', + settings: 'الإعدادات', + dismiss: 'إغلاق دون اختيار', + settingsTitle: 'إعدادات ملفات تعريف الارتباط', + settingsIntro: 'يمكنك تغيير ذلك في أي وقت من «إعدادات ملفات تعريف الارتباط» في تذييل الصفحة.', + necessaryTitle: 'ضرورية', + necessaryBody: 'لازمة لعمل الموقع، لذلك تظل مفعّلة دائمًا.', + necessaryStatus: 'مفعّلة دائمًا', + analyticsTitle: 'إحصاءات الاستخدام (اختيارية)', + analyticsBody: 'إحصاءات استخدام تساعدنا على تحسين الخدمة.', + analyticsSwitch: 'السماح بإحصاءات الاستخدام', + save: 'حفظ الاختيارات', + cancel: 'إلغاء', + close: 'إغلاق', + saved: 'تم حفظ إعدادات ملفات تعريف الارتباط.', + trigger: 'إعدادات ملفات تعريف الارتباط', + }), +}); + +/** + * Strings for a document language: the exact tag, then its base language + * (zh falls to zh-TW only through an explicit tag — a bare `zh` reads + * English, as the site does not serve Simplified Chinese), else English. + * @param {string | null | undefined} lang + * @returns {{ lang: string, messages: Readonly }} + */ +export function consentMessagesFor(lang) { + const tag = typeof lang === 'string' ? lang.trim() : ''; + const exact = Object.keys(CONSENT_MESSAGES).find((key) => key.toLowerCase() === tag.toLowerCase()); + if (exact) return { lang: exact, messages: CONSENT_MESSAGES[exact] }; + const base = tag.split('-')[0].toLowerCase(); + if (base && base !== 'zh' && CONSENT_MESSAGES[base]) return { lang: base, messages: CONSENT_MESSAGES[base] }; + return { lang: 'en', messages: CONSENT_MESSAGES.en }; +} From 3d125cb614c304e8d9ea53e907f7640ea97f47b9 Mon Sep 17 00:00:00 2001 From: Sin-Kang Date: Sat, 14 Nov 2026 14:16:04 +0900 Subject: [PATCH 3/3] test: distinguish shared consent locales from hub UI locales --- tests/consent.test.mjs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tests/consent.test.mjs b/tests/consent.test.mjs index 446c231..60263b7 100644 --- a/tests/consent.test.mjs +++ b/tests/consent.test.mjs @@ -209,14 +209,16 @@ for (const [label, cookie] of [ }); } -test('the bar strings: ko/en are the kit’s, all fourteen hub locales filled', () => { +test('the shared bar strings cover every hub locale and Kannada', () => { assert.deepEqual(CONSENT_MESSAGES.ko, CONSENT_MESSAGES_KO); assert.deepEqual(CONSENT_MESSAGES.en, CONSENT_MESSAGES_EN); const html = readFileSync(join(root, 'index.html'), 'utf8'); const supported = JSON.parse(html.match(/var SUPPORTED = (\[[^\]]+\]);/)[1].replaceAll("'", '"')); - assert.deepEqual(Object.keys(CONSENT_MESSAGES).sort(), [...supported].sort()); + assert.deepEqual(Object.keys(CONSENT_MESSAGES).sort(), [...supported, 'kn'].sort()); + assert.equal(consentMessagesFor('kn-IN').lang, 'kn'); + assert.equal(consentMessagesFor('KN').lang, 'kn'); const keys = Object.keys(CONSENT_MESSAGES_KO).sort(); - for (const lang of supported) { + for (const lang of Object.keys(CONSENT_MESSAGES)) { const m = consentMessagesFor(lang).messages; assert.deepEqual(Object.keys(m).sort(), keys, `${lang}: the kit's keys, learnMore and cancel included`); assert.ok(m.settingsIntro.includes(m.trigger), `${lang}: the settings intro names the footer control`);