Channels: translate the add/delete menu strings; flash.sh rebuilds packs

Add delete_channel and keep_one_channel to the language table (after mute) and
fill all 20 language files (13 translated, English fallback for the rest), with
correct single-byte ISO-8859 accents. Wire them into the Delete Channel label,
confirmation and last-channel guard. The new strings land on empty voice-table
slots, so they play as silence (no crash, no .vpr regeneration).

flash.sh now always rebuilds the .gla language packs so edits to the language
files are actually picked up (previously a stale pack was re-flashed).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Marcus Kida 2026-07-10 12:47:27 +02:00
parent e145a1188d
commit a8c2038552
24 changed files with 56 additions and 8 deletions

View file

@ -15,6 +15,11 @@ single running list until the first versioned release.
- **Delete Channel** — deletes the selected channel after a confirmation, and
scrubs it out of every zone that referenced it. Refuses to delete the last
remaining channel, and respects the read-only/APRS channel lock.
- The new menu strings are **translated** (German, French, Italian, Spanish,
Portuguese, Dutch, Danish, Swedish, Catalan, Finnish, Czech; English fallback
for the rest).
- **`flash.sh`** now always rebuilds the language (`.gla`) packs, so edits to the
language files are picked up instead of a stale pack being re-flashed.
- **Release script** now flags every release before v1.0.0 as a **pre-release**
(and corrects the flag on re-runs).

View file

@ -327,6 +327,8 @@ const stringsTable_t catalanLanguage=
.text_size = "Text size",//MaxLen: 16 (with ':' + 1 digit)
.last_talker = "Last talker", // MaxLen: 16 (with ':' + .off or 2 digits value + 's')
.mute = "Mute", // MaxLen: 16 (with ':' + .on or .off)
.delete_channel = "Esborra canal", // MaxLen: 16
.keep_one_channel = "Deixa 1 canal", // MaxLen: 16
};
/********************************************************************
*

View file

@ -327,6 +327,8 @@ const stringsTable_t croatianLanguage =
.text_size = "Text size",//MaxLen: 16 (with ':' + 1 digit)
.last_talker = "Last talker", // MaxLen: 16 (with ':' + .off or 2 digits value + 's')
.mute = "Mute", // MaxLen: 16 (with ':' + .on or .off)
.delete_channel = "Delete Channel", // MaxLen: 16
.keep_one_channel = "Keep 1 channel", // MaxLen: 16
};
/********************************************************************
*

View file

@ -327,6 +327,8 @@ const stringsTable_t czechLanguage =
.text_size = "Text size",//MaxLen: 16 (with ':' + 1 digit)
.last_talker = "Last talker", // MaxLen: 16 (with ':' + .off or 2 digits value + 's')
.mute = "Mute", // MaxLen: 16 (with ':' + .on or .off)
.delete_channel = "Smazat kanál", // MaxLen: 16
.keep_one_channel = "Nech 1 kanál", // MaxLen: 16
};
/********************************************************************
*

View file

@ -327,6 +327,8 @@ const stringsTable_t danishLanguage =
.text_size = "Text size",//MaxLen: 16 (with ':' + 1 digit)
.last_talker = "Last talker", // MaxLen: 16 (with ':' + .off or 2 digits value + 's')
.mute = "Mute", // MaxLen: 16 (with ':' + .on or .off)
.delete_channel = "Slet kanal", // MaxLen: 16
.keep_one_channel = "Behold 1 kanal", // MaxLen: 16
};
/********************************************************************
*

View file

@ -327,6 +327,8 @@ const stringsTable_t dutchLanguage =
.text_size = "Text size",//MaxLen: 16 (with ':' + 1 digit)
.last_talker = "Last talker", // MaxLen: 16 (with ':' + .off or 2 digits value + 's')
.mute = "Mute", // MaxLen: 16 (with ':' + .on or .off)
.delete_channel = "Kanaal wissen", // MaxLen: 16
.keep_one_channel = "Hou 1 kanaal", // MaxLen: 16
};
/********************************************************************
*

View file

@ -327,6 +327,8 @@ const stringsTable_t englishLanguage =
.text_size = "Text size",//MaxLen: 16 (with ':' + 1 digit)
.last_talker = "Last talker", // MaxLen: 16 (with ':' + .off or 2 digits value + 's')
.mute = "Mute", // MaxLen: 16 (with ':' + .on or .off)
.delete_channel = "Delete Channel", // MaxLen: 16
.keep_one_channel = "Keep 1 channel", // MaxLen: 16
};
/********************************************************************
*

View file

@ -327,6 +327,8 @@ const stringsTable_t finnishLanguage =
.text_size = "Text size",//MaxLen: 16 (with ':' + 1 digit)
.last_talker = "Last talker", // MaxLen: 16 (with ':' + .off or 2 digits value + 's')
.mute = "Mute", // MaxLen: 16 (with ':' + .on or .off)
.delete_channel = "Poista kanava", // MaxLen: 16
.keep_one_channel = "Pidä 1 kanava", // MaxLen: 16
};
/********************************************************************
*

View file

@ -327,6 +327,8 @@ const stringsTable_t frenchLanguage =
.text_size = "Taille texte",//MaxLen: 16 (with ':' + 1 digit)
.last_talker = "Der. locut.", // MaxLen: 16 (with ':' + .off or 2 digits value + 's')
.mute = "Sourdine", // MaxLen: 16 (with ':' + .on or .off)
.delete_channel = "Effacer canal", // MaxLen: 16
.keep_one_channel = "Garder 1 canal", // MaxLen: 16
};
/********************************************************************
*

View file

@ -327,6 +327,8 @@ const stringsTable_t germanLanguage =
.text_size = "Text Grösse",//MaxLen: 16 (with ':' + 1 digit)
.last_talker = "Last talker", // MaxLen: 16 (with ':' + .off or 2 digits value + 's')
.mute = "Mute", // MaxLen: 16 (with ':' + .on or .off)
.delete_channel = "Kanal löschen", // MaxLen: 16
.keep_one_channel = "1 Kanal behalten", // MaxLen: 16
};
/********************************************************************
*

View file

@ -327,6 +327,8 @@ const stringsTable_t hungarianLanguage=
.text_size = "Text size",//MaxLen: 16 (with ':' + 1 digit)
.last_talker = "Last talker", // MaxLen: 16 (with ':' + .off or 2 digits value + 's')
.mute = "Mute", // MaxLen: 16 (with ':' + .on or .off)
.delete_channel = "Delete Channel", // MaxLen: 16
.keep_one_channel = "Keep 1 channel", // MaxLen: 16
};
/********************************************************************
*

View file

@ -327,6 +327,8 @@ const stringsTable_t italianLanguage =
.text_size = "Formato font",//MaxLen: 16 (with ':' + 1 digit)
.last_talker = "Ultimo OM RX", // MaxLen: 16 (with ':' + .off or 2 digits value + 's')
.mute = "Muto", // MaxLen: 16 (with ':' + .on or .off)
.delete_channel = "Elimina canale", // MaxLen: 16
.keep_one_channel = "Tieni 1 canale", // MaxLen: 16
};
/********************************************************************
*

View file

@ -327,6 +327,8 @@ const stringsTable_t japaneseLanguage =
.text_size = "Text size",//MaxLen: 16 (with ':' + 1 digit)
.last_talker = "Last talker", // MaxLen: 16 (with ':' + .off or 2 digits value + 's')
.mute = "Mute", // MaxLen: 16 (with ':' + .on or .off)
.delete_channel = "Delete Channel", // MaxLen: 16
.keep_one_channel = "Keep 1 channel", // MaxLen: 16
};
/********************************************************************
*

View file

@ -327,6 +327,8 @@ const stringsTable_t polishLanguage =
.text_size = "Text size",//MaxLen: 16 (with ':' + 1 digit)
.last_talker = "Last talker", // MaxLen: 16 (with ':' + .off or 2 digits value + 's')
.mute = "Mute", // MaxLen: 16 (with ':' + .on or .off)
.delete_channel = "Delete Channel", // MaxLen: 16
.keep_one_channel = "Keep 1 channel", // MaxLen: 16
};
/********************************************************************
*

View file

@ -327,6 +327,8 @@ const stringsTable_t portuguesBrazilLanguage =
.text_size = "Text size",//MaxLen: 16 (with ':' + 1 digit)
.last_talker = "Last talker", // MaxLen: 16 (with ':' + .off or 2 digits value + 's')
.mute = "Mute", // MaxLen: 16 (with ':' + .on or .off)
.delete_channel = "Apagar canal", // MaxLen: 16
.keep_one_channel = "Manter 1 canal", // MaxLen: 16
};
/*********************************************************************
*

View file

@ -327,6 +327,8 @@ const stringsTable_t portuguesLanguage =
.text_size = "Text size",//MaxLen: 16 (with ':' + 1 digit)
.last_talker = "Last talker", // MaxLen: 16 (with ':' + .off or 2 digits value + 's')
.mute = "Mute", // MaxLen: 16 (with ':' + .on or .off)
.delete_channel = "Apagar canal", // MaxLen: 16
.keep_one_channel = "Manter 1 canal", // MaxLen: 16
};
/********************************************************************
*

View file

@ -327,6 +327,8 @@ const stringsTable_t romanianLanguage =
.text_size = "Text size",//MaxLen: 16 (with ':' + 1 digit)
.last_talker = "Last talker", // MaxLen: 16 (with ':' + .off or 2 digits value + 's')
.mute = "Mute", // MaxLen: 16 (with ':' + .on or .off)
.delete_channel = "Delete Channel", // MaxLen: 16
.keep_one_channel = "Keep 1 channel", // MaxLen: 16
};
/********************************************************************
*

View file

@ -327,6 +327,8 @@ const stringsTable_t slovenianLanguage =
.text_size = "Text size",//MaxLen: 16 (with ':' + 1 digit)
.last_talker = "Last talker", // MaxLen: 16 (with ':' + .off or 2 digits value + 's')
.mute = "Mute", // MaxLen: 16 (with ':' + .on or .off)
.delete_channel = "Delete Channel", // MaxLen: 16
.keep_one_channel = "Keep 1 channel", // MaxLen: 16
};
/********************************************************************
*

View file

@ -327,6 +327,8 @@ const stringsTable_t spanishLanguage =
.text_size = "Text size",//MaxLen: 16 (with ':' + 1 digit)
.last_talker = "Last talker", // MaxLen: 16 (with ':' + .off or 2 digits value + 's')
.mute = "Mute", // MaxLen: 16 (with ':' + .on or .off)
.delete_channel = "Borrar canal", // MaxLen: 16
.keep_one_channel = "Dejar 1 canal", // MaxLen: 16
};
/********************************************************************
*

View file

@ -327,6 +327,8 @@ const stringsTable_t swedishLanguage =
.text_size = "Text size",//MaxLen: 16 (with ':' + 1 digit)
.last_talker = "Last talker", // MaxLen: 16 (with ':' + .off or 2 digits value + 's')
.mute = "Mute", // MaxLen: 16 (with ':' + .on or .off)
.delete_channel = "Radera kanal", // MaxLen: 16
.keep_one_channel = "Behåll 1 kanal", // MaxLen: 16
};
/********************************************************************
*

View file

@ -327,6 +327,8 @@ const stringsTable_t turkishLanguage =
.text_size = "Text size",//MaxLen: 16 (with ':' + 1 digit)
.last_talker = "Last talker", // MaxLen: 16 (with ':' + .off or 2 digits value + 's')
.mute = "Mute", // MaxLen: 16 (with ':' + .on or .off)
.delete_channel = "Delete Channel", // MaxLen: 16
.keep_one_channel = "Keep 1 channel", // MaxLen: 16
};
/********************************************************************
*

View file

@ -335,6 +335,8 @@ typedef struct
const char text_size[LANGUAGE_TEXTS_LENGTH];
const char last_talker[LANGUAGE_TEXTS_LENGTH];
const char mute[LANGUAGE_TEXTS_LENGTH];
const char delete_channel[LANGUAGE_TEXTS_LENGTH];
const char keep_one_channel[LANGUAGE_TEXTS_LENGTH];
} stringsTable_t;
#endif // _OPENGD77_UILANGUAGE_H_

View file

@ -2416,7 +2416,7 @@ static void updateQuickMenuScreen(bool isFirstRun)
rightSideConst = currentLanguage->new_channel;
break;
case CH_SCREEN_QUICK_MENU_DELETE_CHANNEL:
rightSideConst = "Delete Channel";
rightSideConst = currentLanguage->delete_channel;
break;
default:
buf[0] = 0;
@ -2683,7 +2683,7 @@ static void handleQuickMenuEvent(uiEvent_t *ev)
if (inUseCount < 2)
{
snprintf(uiDataGlobal.MessageBox.message, MESSAGEBOX_MESSAGE_LEN_MAX, "Cannot delete\nlast channel");
snprintf(uiDataGlobal.MessageBox.message, MESSAGEBOX_MESSAGE_LEN_MAX, "%s", currentLanguage->keep_one_channel);
uiDataGlobal.MessageBox.buttons =
#if defined(PLATFORM_MD9600)
MESSAGEBOX_BUTTONS_ENT;
@ -2695,12 +2695,13 @@ static void handleQuickMenuEvent(uiEvent_t *ev)
return;
}
snprintf(uiDataGlobal.MessageBox.message, MESSAGEBOX_MESSAGE_LEN_MAX, "Delete channel?\n%s", currentLanguage->please_confirm);
snprintf(uiDataGlobal.MessageBox.message, MESSAGEBOX_MESSAGE_LEN_MAX, "%s\n%s", currentLanguage->delete_channel, currentLanguage->please_confirm);
uiDataGlobal.MessageBox.buttons = MESSAGEBOX_BUTTONS_YESNO;
uiDataGlobal.MessageBox.validatorCallback = validateDeleteChannel;
menuSystemPushNewMenu(UI_MESSAGE_BOX);
voicePromptsInit();
voicePromptsAppendLanguageString(currentLanguage->delete_channel);
voicePromptsAppendLanguageString(currentLanguage->please_confirm);
voicePromptsPlay();
return;

View file

@ -58,11 +58,11 @@ done
# ---- resolve / build the language file ------------------------------------
LANG_ARGS=()
if [[ -n "$LANGUAGE" && "$(lc "$LANGUAGE")" != "none" ]]; then
# Build the .gla files once if they're missing.
if ! ls "$LANG_SRC"/*.gla >/dev/null 2>&1; then
# Always (re)build the .gla language packs so edits to the *.h language files
# are picked up. (They're built from the .h sources by languages_builder; a
# stale pack would otherwise show blank/old strings on the radio.)
echo "==> Building language (.gla) files..."
( cd "$LANG_SRC" && gcc -w -I../ -o languages_builder languages_builder.c && ./languages_builder >/dev/null )
fi
# Case-insensitive match of the requested name to an actual <Name>.gla file.
GLA=""
for f in "$LANG_SRC"/*.gla; do