Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
c39935f
delete i18n subtree
catreedle Dec 26, 2025
84429a5
Add Scribe-i18n as git submodule
catreedle Dec 26, 2025
50392fc
Update i18n script for submodules
catreedle Dec 26, 2025
e190723
add submodules on git clone
catreedle Dec 26, 2025
c6be0ad
Update Android CI to checkout git submodules
catreedle Dec 26, 2025
b36d05e
docs: clarify submodule setup for existing contributors
catreedle Dec 26, 2025
3fbe327
Merge branch 'scribe-org:main' into submodule-i18n
catreedle Dec 26, 2025
330ae07
add submodules on git clone ssh
catreedle Dec 26, 2025
5b78ece
Uopdate documetnation and version of Scribe-i18n
andrewtavis Dec 26, 2025
6d8d32b
Update version of Scribe-i18n
catreedle Dec 29, 2025
a6a3374
update i18n directory
catreedle Dec 29, 2025
3df0367
update i18n version
catreedle Dec 29, 2025
eccaa22
update generated string.xml
catreedle Dec 29, 2025
9ff114f
update string keys
catreedle Dec 29, 2025
88f474c
Merge remote-tracking branch 'upstream/main' into submodule-i18n
catreedle Dec 29, 2025
d34f646
fix DownloadState variables
catreedle Dec 29, 2025
3eb0a3d
add stringResourceWithParams helper
catreedle Dec 29, 2025
6d4ad4c
update i18n keys
catreedle Dec 29, 2025
0f2b14d
update i18n version
catreedle Dec 29, 2025
90b8914
update i18n version
catreedle Dec 29, 2025
fa928ab
fix i18n global keys
catreedle Dec 29, 2025
3d2275d
convert _global strings
catreedle Dec 29, 2025
0452b05
fix i18n keys for test files
catreedle Dec 29, 2025
874e17b
fix i18n keys for test files
catreedle Dec 29, 2025
445614b
update documentation with submodule
catreedle Dec 30, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .github/workflows/android_ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
submodules: true

- name: Prepare App
uses: ./.github/composite/prepareApp
Expand All @@ -32,6 +34,8 @@ jobs:
steps:
- name: Checkout Repository
uses: actions/checkout@v4
with:
submodules: true

- name: Prepare App
uses: ./.github/composite/prepareApp
Expand All @@ -44,6 +48,8 @@ jobs:
steps:
- name: Checkout Repository
uses: actions/checkout@v4
with:
submodules: true

- name: Set up JDK
uses: actions/setup-java@v1
Expand All @@ -65,6 +71,8 @@ jobs:
steps:
- name: Checkout Repository
uses: actions/checkout@v4
with:
submodules: true

- name: Prepare App
uses: ./.github/composite/prepareApp
Expand All @@ -86,6 +94,8 @@ jobs:
steps:
- name: Checkout Repository
uses: actions/checkout@v4
with:
submodules: true

- name: Prepare App
uses: ./.github/composite/prepareApp
Expand Down
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "app/src/main/assets/i18n"]
path = app/src/main/assets/i18n
url = https://github.com/scribe-org/Scribe-i18n.git
11 changes: 7 additions & 4 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,16 +90,19 @@ Scribe-Android is developed using the [Kotlin](https://kotlinlang.org/) coding l
>
> To run git commands with SSH, remember then to substitute the HTTPS URL, `https://github.com/...`, with the SSH one, `git@github.com:...`.
>
> - e.g. Cloning now becomes `git clone git@github.com:<your-username>/Scribe-Android.git`
> - e.g. Cloning (with submodules) now becomes `git clone --recurse-submodules git@github.com:<your-username>/Scribe-Android.git`
>
> GitHub also has their documentation on how to [Generate a new SSH key](https://docs.github.com/en/authentication/connecting-to-github-with-ssh/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent) 🔑
>
> </p>
> </details>

> [!NOTE]
> Cloning this repository with `--recurse-submodules` also clones a copy of [Scribe-i18n](https://github.com/scribe-org/Scribe-i18n) where the texts for Scribe projects are localized. When pulling changes from `main`, you should also run the following command: `git submodule update --init --recursive`.

```bash
# Clone your fork of the repo into the current directory.
git clone https://github.com/<your-username>/Scribe-Android.git
# Clone your fork of the repo into the current directory (including submodules).
git clone --recurse-submodules https://github.com/<your-username>/Scribe-Android.git
# Navigate to the newly cloned directory.
cd Scribe-Android
# Assign the original repo to a remote called "upstream".
Expand Down Expand Up @@ -337,7 +340,7 @@ Scribe does not accept direct edits to the grammar files as they are sourced fro

Being an app that focusses on language learning, localization plays a big part in what Scribe will eventually be. Those interested are more than welcome to join the team at [scribe-org/Scribe-i18n](https://github.com/scribe-org/Scribe-i18n) where we work on localizing all Scribe applications via [Weblate](https://weblate.org/).

Please run the [update_i18n_keys.sh](https://github.com/scribe-org/Scribe-Android/blob/main/update_i18n_keys.sh) script to load in the most recent version of the [Scribe-i18n](https://github.com/scribe-org/Scribe-i18n) app texts into Scribe-Android.
Please run the [update_i18n_keys.sh](./update_i18n_keys.sh) script to load in the most recent version of the [Scribe-i18n](https://github.com/scribe-org/Scribe-i18n) app texts into Scribe-Android.

### Progress

Expand Down
9 changes: 6 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -137,16 +137,19 @@ Scribe-Android is developed using the [Kotlin](https://kotlinlang.org/) coding l
>
> To run git commands with SSH, remember then to substitute the HTTPS URL, `https://github.com/...`, with the SSH one, `git@github.com:...`.
>
> - e.g. Cloning now becomes `git clone git@github.com:<your-username>/Scribe-Android.git`
> - e.g. Cloning (with submodules) now becomes `git clone --recurse-submodules git@github.com:<your-username>/Scribe-Android.git`
>
> GitHub also has their documentation on how to [Generate a new SSH key](https://docs.github.com/en/authentication/connecting-to-github-with-ssh/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent) 🔑
>
> </p>
> </details>

> [!NOTE]
> Cloning this repository with `--recurse-submodules` also clones a copy of [Scribe-i18n](https://github.com/scribe-org/Scribe-i18n) where the texts for Scribe projects are localized. When pulling changes from `main`, you should also run the following command: `git submodule update --init --recursive`.

```bash
# Clone your fork of the repo into the current directory.
git clone https://github.com/<your-username>/Scribe-Android.git
# Clone your fork of the repo into the current directory (including submodules).
git clone --recurse-submodules https://github.com/<your-username>/Scribe-Android.git
# Navigate to the newly cloned directory.
cd Scribe-Android
# Assign the original repo to a remote called "upstream".
Expand Down
4 changes: 2 additions & 2 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -307,13 +307,13 @@ tasks.register<Copy>("moveFromi18n") {
destinationDir = file("src/main/res")

val locales =
file("src/main/assets/i18n/Scribe-i18n/values")
file("src/main/assets/i18n/i18n/values")
.listFiles()
?.filter { it.isDirectory }
?.map { it.name }
?: emptyList()
locales.forEach { locale ->
val fromDir = file("src/main/assets/i18n/Scribe-i18n/values/$locale/")
val fromDir = file("src/main/assets/i18n/i18n/values/$locale/")
val targetDir =
if (locale == "en-US") {
"values"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,15 +152,15 @@ class AboutUtilInstrumentedTest {
// Test specific items.
val githubItem = communityList.items[0] as ScribeItem.ExternalLinkItem
assertThat(githubItem.leadingIcon).isEqualTo(R.drawable.github_logo)
assertThat(githubItem.title).isEqualTo(R.string.app_about_community_github)
assertThat(githubItem.title).isEqualTo(R.string.i18n_app_about_community_github)

val shareItem = communityList.items[1] as ScribeItem.ExternalLinkItem
assertThat(shareItem.leadingIcon).isEqualTo(R.drawable.share_icon)
assertThat(shareItem.title).isEqualTo(R.string.app_about_community_share_scribe)
assertThat(shareItem.title).isEqualTo(R.string.i18n_app_about_community_share_scribe)

val wikimediaItem = communityList.items[2] as ScribeItem.ExternalLinkItem
assertThat(wikimediaItem.leadingIcon).isEqualTo(R.drawable.wikimedia_logo_black)
assertThat(wikimediaItem.title).isEqualTo(R.string.app_about_community_wikimedia)
assertThat(wikimediaItem.title).isEqualTo(R.string.i18n_app_about_community_wikimedia)

// Test onClick callbacks.
shareItem.onClick()
Expand Down Expand Up @@ -216,15 +216,15 @@ class AboutUtilInstrumentedTest {
// Test specific items.
val rateItem = feedbackList.items[0] as ScribeItem.ExternalLinkItem
assertThat(rateItem.leadingIcon).isEqualTo(R.drawable.star)
assertThat(rateItem.title).isEqualTo(R.string.app_about_feedback_rate_scribe)
assertThat(rateItem.title).isEqualTo(R.string.i18n_app_about_feedback_rate_scribe)

val mailItem = feedbackList.items[2] as ScribeItem.ExternalLinkItem
assertThat(mailItem.leadingIcon).isEqualTo(R.drawable.mail_icon)
assertThat(mailItem.title).isEqualTo(R.string.app_about_feedback_email)
assertThat(mailItem.title).isEqualTo(R.string.i18n_app_about_feedback_send_email)

val hintsItem = feedbackList.items[4] as ScribeItem.ExternalLinkItem
assertThat(hintsItem.leadingIcon).isEqualTo(R.drawable.light_bulb_icon)
assertThat(hintsItem.title).isEqualTo(R.string.app_about_feedback_app_hints)
assertThat(hintsItem.title).isEqualTo(R.string.i18n_app_about_feedback_reset_app_hints)

// Test onClick callbacks.
rateItem.onClick()
Expand Down Expand Up @@ -279,12 +279,12 @@ class AboutUtilInstrumentedTest {
// Test specific items.
val privacyItem = legalList.items[0] as ScribeItem.ExternalLinkItem
assertThat(privacyItem.leadingIcon).isEqualTo(R.drawable.shield_lock)
assertThat(privacyItem.title).isEqualTo(R.string.app_about_legal_privacy_policy)
assertThat(privacyItem.title).isEqualTo(R.string.i18n__global_privacy_policy)
assertThat(privacyItem.trailingIcon).isEqualTo(R.drawable.right_arrow)

val licenseItem = legalList.items[1] as ScribeItem.ExternalLinkItem
assertThat(licenseItem.leadingIcon).isEqualTo(R.drawable.license_icon)
assertThat(licenseItem.title).isEqualTo(R.string.app_about_legal_third_party)
assertThat(licenseItem.title).isEqualTo(R.string.i18n_app_about_legal_third_party)
assertThat(licenseItem.trailingIcon).isEqualTo(R.drawable.right_arrow)

// Test onClick callbacks.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,12 @@ class ScribeItemListTest {
val items =
listOf(
ScribeItem.ClickableItem(
title = R.string.app_settings_menu_app_language,
desc = R.string.app_settings_menu_app_language_description,
title = R.string.i18n_app_settings_menu_app_language,
desc = R.string.i18n_app_settings_menu_app_language_description,
action = { },
),
ScribeItem.ClickableItem(
title = R.string.app_settings_keyboard_title,
title = R.string.i18n_app_settings_keyboard_title,
desc = null,
action = { },
),
Expand All @@ -76,13 +76,13 @@ class ScribeItemListTest {
val items =
listOf(
ScribeItem.SwitchItem(
title = R.string.app_settings_menu_app_color_mode,
desc = R.string.app_settings_menu_app_color_mode_description,
title = R.string.i18n_app_settings_menu_app_color_mode,
desc = R.string.i18n_app_settings_menu_app_color_mode_description,
state = false,
onToggle = { },
),
ScribeItem.SwitchItem(
title = R.string.app_settings_keyboard_title,
title = R.string.i18n_app_settings_keyboard_title,
desc = 0,
state = true,
onToggle = { },
Expand Down Expand Up @@ -114,8 +114,8 @@ class ScribeItemListTest {
val items =
listOf(
ScribeItem.ClickableItem(
title = R.string.app_settings_menu_app_language,
desc = R.string.app_settings_menu_app_language_description,
title = R.string.i18n_app_settings_menu_app_language,
desc = R.string.i18n_app_settings_menu_app_language_description,
action = { clicked = true },
),
)
Expand All @@ -134,8 +134,8 @@ class ScribeItemListTest {
val items =
listOf(
ScribeItem.SwitchItem(
title = R.string.app_settings_menu_app_color_mode,
desc = R.string.app_settings_menu_app_color_mode_description,
title = R.string.i18n_app_settings_menu_app_color_mode,
desc = R.string.i18n_app_settings_menu_app_color_mode_description,
state = state,
onToggle = { state = it },
),
Expand All @@ -154,8 +154,8 @@ class ScribeItemListTest {
val items =
(0..49).map { index ->
ScribeItem.ClickableItem(
title = R.string.app_settings_menu_app_language,
desc = R.string.app_settings_menu_app_language_description,
title = R.string.i18n_app_settings_menu_app_language,
desc = R.string.i18n_app_settings_menu_app_language_description,
action = { },
)
}
Expand Down Expand Up @@ -190,8 +190,8 @@ class ScribeItemListTest {
val items =
listOf(
ScribeItem.ClickableItem(
title = R.string.app_settings_menu_app_language,
desc = R.string.app_settings_menu_app_language_description,
title = R.string.i18n_app_settings_menu_app_language,
desc = R.string.i18n_app_settings_menu_app_language_description,
action = { },
),
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class SettingsScreenInstallKeyboardButtonTest {
@Test
fun installKeyboardButton_isDisplayed_whenKeyboardNotInstalled() {
val context = InstrumentationRegistry.getInstrumentation().targetContext
val expectedText = context.getString(R.string.app_settings_button_install_keyboards)
val expectedText = context.getString(R.string.i18n_app_settings_button_install_keyboards)
val mockViewModel = createMockViewModel(isKeyboardInstalled = false)

composeTestRule.setContent {
Expand All @@ -58,7 +58,7 @@ class SettingsScreenInstallKeyboardButtonTest {
@Test
fun installKeyboardButton_isNotDisplayed_whenKeyboardInstalled() {
val context = InstrumentationRegistry.getInstrumentation().targetContext
val expectedText = context.getString(R.string.app_settings_button_install_keyboards)
val expectedText = context.getString(R.string.i18n_app_settings_button_install_keyboards)
val mockViewModel = createMockViewModel(isKeyboardInstalled = true)

every { mockViewModel.languages } returns MutableStateFlow(listOf("English", "German"))
Expand All @@ -82,7 +82,7 @@ class SettingsScreenInstallKeyboardButtonTest {
@Test
fun installKeyboardButton_hasClickAction_whenDisplayed() {
val context = InstrumentationRegistry.getInstrumentation().targetContext
val expectedText = context.getString(R.string.app_settings_button_install_keyboards)
val expectedText = context.getString(R.string.i18n_app_settings_button_install_keyboards)
val mockViewModel = createMockViewModel(isKeyboardInstalled = false)

composeTestRule.setContent {
Expand All @@ -105,7 +105,7 @@ class SettingsScreenInstallKeyboardButtonTest {
@Test
fun installKeyboardButton_performClick_buttonStillExists() {
val context = InstrumentationRegistry.getInstrumentation().targetContext
val expectedText = context.getString(R.string.app_settings_button_install_keyboards)
val expectedText = context.getString(R.string.i18n_app_settings_button_install_keyboards)
val mockViewModel = createMockViewModel(isKeyboardInstalled = false)

composeTestRule.setContent {
Expand All @@ -129,7 +129,7 @@ class SettingsScreenInstallKeyboardButtonTest {
@Test
fun installKeyboardButton_displaysCorrectText() {
val context = InstrumentationRegistry.getInstrumentation().targetContext
val expectedText = context.getString(R.string.app_settings_button_install_keyboards)
val expectedText = context.getString(R.string.i18n_app_settings_button_install_keyboards)
val mockViewModel = createMockViewModel(isKeyboardInstalled = false)

composeTestRule.setContent {
Expand All @@ -152,7 +152,7 @@ class SettingsScreenInstallKeyboardButtonTest {
@Test
fun installKeyboardButton_rendersCorrectly_inLightTheme() {
val context = InstrumentationRegistry.getInstrumentation().targetContext
val expectedText = context.getString(R.string.app_settings_button_install_keyboards)
val expectedText = context.getString(R.string.i18n_app_settings_button_install_keyboards)
val mockViewModel = createMockViewModel(isKeyboardInstalled = false)

composeTestRule.setContent {
Expand All @@ -176,7 +176,7 @@ class SettingsScreenInstallKeyboardButtonTest {
@Test
fun installKeyboardButton_rendersCorrectly_inDarkTheme() {
val context = InstrumentationRegistry.getInstrumentation().targetContext
val expectedText = context.getString(R.string.app_settings_button_install_keyboards)
val expectedText = context.getString(R.string.i18n_app_settings_button_install_keyboards)
val mockViewModel = createMockViewModel(isKeyboardInstalled = false)

every { mockViewModel.isUserDarkMode } returns MutableStateFlow(true)
Expand All @@ -202,7 +202,7 @@ class SettingsScreenInstallKeyboardButtonTest {
@Test
fun installKeyboardButton_hasProperStyling() {
val context = InstrumentationRegistry.getInstrumentation().targetContext
val expectedText = context.getString(R.string.app_settings_button_install_keyboards)
val expectedText = context.getString(R.string.i18n_app_settings_button_install_keyboards)
val mockViewModel = createMockViewModel(isKeyboardInstalled = false)

composeTestRule.setContent {
Expand Down
Loading
Loading