From aab29da1481b2249b29cc93891cde89f716fd6d6 Mon Sep 17 00:00:00 2001 From: Linus Rath <139418639+rathlinus@users.noreply.github.com> Date: Thu, 24 Sep 2026 20:23:34 +0200 Subject: [PATCH] fix: translate the file sharing roles and label the files toolbar The share sheet asked for files.share_role_* keys that no catalog has, so Viewer, Editor and Manager stayed English everywhere; it now uses the webmail's sharing.preset names and its "Share \"{name}\"" title. The per-file menu, back and clear-selection buttons get screen reader labels, and the "sharing is not available" error is translated. --- locales/rn/en.json | 1 + src/components/__tests__/screens-i18n.test.ts | 23 +++++++++++++++++++ src/components/files/ShareSheet.tsx | 11 +++++---- src/screens/FilesScreen.tsx | 20 +++++++++++++--- 4 files changed, 48 insertions(+), 7 deletions(-) create mode 100644 src/components/__tests__/screens-i18n.test.ts diff --git a/locales/rn/en.json b/locales/rn/en.json index 2fab8f32..aeabcaa4 100644 --- a/locales/rn/en.json +++ b/locales/rn/en.json @@ -375,6 +375,7 @@ "share_remove": "Remove access", "share_role_custom": "Custom", "share_search_placeholder": "Search by name or email", + "share_unavailable": "Sharing is not available on this device", "shared_with": "Shared with", "sharing_access": "Sharing & access", "upload_unavailable": "The file picker is not installed in this build. Rebuild the app to enable uploads." diff --git a/src/components/__tests__/screens-i18n.test.ts b/src/components/__tests__/screens-i18n.test.ts new file mode 100644 index 00000000..aa81c6b4 --- /dev/null +++ b/src/components/__tests__/screens-i18n.test.ts @@ -0,0 +1,23 @@ +// Screens and sheets outside Settings and Contacts whose every user-visible +// string goes through t(). A literal English label, alert or JSX text +// sneaking back in stays English in every locale, so this scans the source. +import { describe, it, expect } from 'vitest'; +import { join } from 'node:path'; +import { findUntranslatedLiterals } from './untranslated-literals'; + +const SRC = join(__dirname, '..', '..'); + +// File (relative to src/) → texts that stay as they are on purpose. +const TRANSLATED_FILES: Record = { + 'screens/FilesScreen.tsx': [], + 'components/files/ShareSheet.tsx': [], + 'components/files/FilePreviewModal.tsx': [], +}; + +describe('translated screens', () => { + for (const [file, allow] of Object.entries(TRANSLATED_FILES)) { + it(`${file} has no hard-coded English text`, () => { + expect(findUntranslatedLiterals(join(SRC, file), allow)).toEqual([]); + }); + } +}); diff --git a/src/components/files/ShareSheet.tsx b/src/components/files/ShareSheet.tsx index 4f726119..168b7db6 100644 --- a/src/components/files/ShareSheet.tsx +++ b/src/components/files/ShareSheet.tsx @@ -39,10 +39,11 @@ const FILE_PRESETS: Record = { }, }; +// The webmail's sharing presets (same rights, same names). const PRESET_LABEL_KEYS: Record = { - read: ['files.share_role_viewer', 'Viewer'], - readWrite: ['files.share_role_editor', 'Editor'], - manager: ['files.share_role_manager', 'Manager'], + read: ['sharing.preset.read', 'Read only'], + readWrite: ['sharing.preset.readWrite', 'Read & write'], + manager: ['sharing.preset.manager', 'Manager'], }; const PRESET_ORDER: RolePreset[] = ['read', 'readWrite', 'manager']; @@ -159,7 +160,7 @@ export default function ShareSheet({ node, onClose, onChanged }: ShareSheetProps - {t('files.share', 'Share')} “{node.name}” + {t('sharing.title', 'Share "{name}"', { name: node.name })} {isFolder(node) ? ( @@ -188,6 +189,8 @@ export default function ShareSheet({ node, onClose, onChanged }: ShareSheetProps onPress={() => void applyShare(principalId, FILE_PRESETS[p])} disabled={busy} style={[styles.chip, preset === p && styles.chipActive]} + accessibilityRole="button" + accessibilityState={{ selected: preset === p, disabled: busy }} > - + @@ -711,7 +717,13 @@ export default function FilesScreen() { {canBack ? ( - + ) : null} @@ -890,6 +902,8 @@ export default function FilesScreen() { }} hitSlop={8} style={styles.rowMore} + accessibilityRole="button" + accessibilityLabel={t('files.context_menu', 'Actions')} >