Skip to content
Snippets Groups Projects
Commit 483a260c authored by Elmar Ludwig's avatar Elmar Ludwig
Browse files

rework and fix handling of JS translations, re #5

parent 98d7db55
No related branches found
No related tags found
No related merge requests found
CODECEPT = composer/bin/codecept
SVGO = node_modules/svgo/bin/svgo
CATALOGS = locale/en/LC_MESSAGES/studip.mo locale/en/LC_MESSAGES/js-resources.json
NPM_BIN = $(shell npm bin)
RESOURCES = $(shell find resources -type f)
PHP_SOURCES = $(shell find app config lib public templates -name '*.php' \( ! -path 'public/plugins_packages/*' -o -path 'public/plugins_packages/core/*' \))
VUE_SOURCES = $(shell find resources -name '*.js' -o -name '*.vue')
# build all needed files
build: composer webpack-prod
......@@ -75,14 +79,30 @@ test-jsonapi: $(CODECEPT)
test-unit: $(CODECEPT)
$(CODECEPT) run unit
catalogs: npm $(CATALOGS)
optimize-icons: npm
$(SVGO) --config=config/svgo.config.js -f public/assets/images/icons/black -r
$(SVGO) --config=config/svgo.config.js -f public/assets/images/icons/blue -r
$(SVGO) --config=config/svgo.config.js -f public/assets/images/icons/green -r
$(SVGO) --config=config/svgo.config.js -f public/assets/images/icons/grey -r
$(SVGO) --config=config/svgo.config.js -f public/assets/images/icons/red -r
$(SVGO) --config=config/svgo.config.js -f public/assets/images/icons/white -r
$(SVGO) --config=config/svgo.config.js -f public/assets/images/icons/yellow -r
find public/assets/images/icons -type f | xargs -P0 $(NPM_BIN)/svgo -q --config=config/svgo.config.js
# default rules for gettext handling
%.pot: $(PHP_SOURCES)
xgettext -o $@ --from-code=UTF-8 $(PHP_SOURCES)
%.po: %.pot
msgmerge -qU $@ $<
%.mo: %.po
msgfmt -o $@ $<
js-%.pot: $(VUE_SOURCES)
$(NPM_BIN)/gettext-extract --attribute v-translate --output $@ $(VUE_SOURCES)
js-%.po: js-%.pot
msgmerge -qU -C $(dir $@)studip.po $@ $<
js-%.json: js-%.po
$(NPM_BIN)/gettext-compile --output $@ $<
sed -i 's/^{[^{]*//;s/}$$//' $@
# dummy target to force update of "doc" target
force_update:
<?php
namespace Studip\Cli\Commands\Translations;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
class VueGettextSplitTranslations extends Command
{
protected static $defaultName = 'translations:vue-gettext-split';
protected function configure(): void
{
$this->setDescription('Split vue-gettext.');
$this->setHelp('Split vue-gettext translations');
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
$translationsFile = $GLOBALS['STUDIP_BASE_PATH'] . '/resources/locales/translations.json';
if (file_exists($translationsFile)) {
$file = file_get_contents($translationsFile);
$json = json_decode($file, true);
foreach ($json as $lang => $content) {
$langFile = realpath(__DIR__ . '/../resources/locales/') . '/' . $lang . '.json';
file_put_contents($langFile, json_encode($content));
}
return Command::SUCCESS;
} else {
$output->writeln(sprintf('<error>Could not find translations in %s</error>', $translationsFile));
return Command::FAILURE;
}
}
}
......@@ -51,7 +51,6 @@ $commands = [
Commands\Plugins\I18N\I18NCompile::class,
Commands\Resources\UpdateBookingIntervals::class,
Commands\SORM\DescribeModels::class,
Commands\Translations\VueGettextSplitTranslations::class,
Commands\Users\UserDelete::class,
Commands\Users\UserDelete::class,
];
......
#!/bin/sh
#
# STEP 2:
# convert all Stud.IP message strings into a binary format
#
LOCALE_RELATIVE_PATH="."
for language in en
do
test -f "$LOCALE_RELATIVE_PATH/$language/LC_MESSAGES/studip.mo" && mv "$LOCALE_RELATIVE_PATH/$language/LC_MESSAGES/studip.mo" "$LOCALE_RELATIVE_PATH/$language/LC_MESSAGES/studip.mo.old"
msgfmt "$LOCALE_RELATIVE_PATH/$language/LC_MESSAGES/studip.po" --output-file="$LOCALE_RELATIVE_PATH/$language/LC_MESSAGES/studip.mo"
done
{"[versteckt]":"[hidden]","[Vertretung]":"[Substitute]","Abbrechen":"Cancel","Abschicken":"Submit","Abschnitt":"Section","Abschnitt bearbeiten":"Edit section","Abschnitt löschen":"Delete section","Aktionen":"Actions","Aktionsmenü":"Action menu","Aktivitäten":"Activities","Allgemeine Einstellungen":"General settings","Anmelderegel konfigurieren":"Configure admission setting","Antwort":"Reply","April":"April","August":"August","Autor":"Author","Autor/-in":"Author","Bearbeiten":"Edit","beliebig":"any","Benachrichtigungen aktiviert":"Notifications activated","Benachrichtigungen für diese Konversation abstellen.":"Unsubscribe from notifications for this conversation.","Beschreibung":"Description","Bezeichnung":"Notation","Bild":"Picture","Bild löschen":"Delete picture","bis":"until","Bitte bestätigen Sie die Aktion":"Please confirm action","Bitte geben Sie Ihren tatsächlichen Nachnamen an.":"Please enter your real last name.","Blenden Sie die restlichen Termine ein":"Show the remaining dates","Breite":"Width","Das Herunterladen dieser Datei ist nur eingeschränkt möglich.":"The download of this file is restricted.","Das Passwort ist zu kurz. Es sollte mindestens 8 Zeichen lang sein.":"The password is too short. It should have at least 8 characters.","Datei hochladen":"Upload file","Dateibereich":"File area","Dateien":"Files","Dateityp":"File type","Datum":"Date","Detailanzeige umschalten":"Switch detailed view","Dezember":"December","Di":"Tue.","Die Teilnahme ist bindend. Bitte wenden Sie sich an die Lehrenden.":"Participation is binding. Please contact the lecturers.","Dienstag":"Tuesday","Dieser Ordner ist leer":"This folder is empty","Do":"Thu.","Dokument hinzufügen":"Add document","Dokument suchen":"Search document","Donnerstag":"Thursday","Downloads":"Downloads","Einstellungen":"Settings","Entwurf":"Draft","Erlauben":"Allow","Erstellen":"Create","Es wurden keine Veranstaltungen gefunden.":"No course found.","Export":"Export","Exportieren":"Export","Extern":"External","Fach löschen":"Delete field of study","Farbgruppierung ändern":"Change colour grouping","Favoriten":"Favourites","Februar":"February","Feedback":"Feedback","Fehler":"Error","Fortschritt":"Progress","Fr":"Fri.","Freitag":"Friday","Gelb":"Yellow","groß":"large","Größe":"Size","Grün":"Green","Grunddaten":"Basic details","Gruppe":"Group","Gruppen":"Groups","HH:mm":"HH:mm","hinzufügen":"add","Höhe":"Height","Icon":"Icon","Importieren":"Import","Information":"Information","Informationen":"Information","Inhalt":"Content","Intern":"Internal","Ja":"Yes","Januar":"January","Juli":"July","Juni":"June","Keine":"None","Keine Auswahl":"No selection","Keine Dateien vorhanden":"No files available","klein":"small","Kommentare":"Comments","Kommentare anzeigen":"Show comments","Kopieren":"Copy","Lesen":"Read","Leser/-innen":"Readers","Liste":"List","Mai":"May","März":"March","Mi":"Wed.","Minute":"Minute","Minuten":"Minutes","Mittwoch":"Wednesday","Mo":"Mon.","Modul suchen":"Search for module","Montag":"Monday","Nachrichtenbox schließen":"Close message box","Name":"Name","Navigation":"Navigation","Nein":"No","normal":"normal","November":"November","Nr.":"No.","Nur buchbare Räume anzeigen":"Display bookable rooms only","oder":"or","Ok":"Ok","Oktober":"October","Ordner":"Folder","Quelle":"Resource","Quelle auswählen":"Select source","Rot":"Red","Sa":"Sat.","Samstag":"Saturday","Schliessen":"Close","Schließen":"Close","Seite bearbeiten":"Edit page","Seite löschen":"Delete page","Sekunden":"Seconds","September":"September","Sichtbar ab":"Visible from","Sichtbarkeit":"Visibility","Sie haben nicht angegeben, wer die Nachricht empfangen soll!":"You did not specify who should receive the message!","Sie haben noch keine Anmelderegeln festgelegt.":"You haven't yet defined any admission rule.","Smileys":"Smileys","So":"Sun.","Sonntag":"Sunday","Sonstiges":"Miscellanea","Speichern":"Save","Sprache":"Language","Standard":"Standard","Status":"Status","Studiengang suchen":"Search course of study","Studiengangteil suchen":"Search course of study","Studierende":"Students","Stunde":"Hour","Suche zurücksetzen":"Reset search","Suche...":"Searching...","Suchergebnisse":"Search results","Tag":"Day","Tage":"Days","Text":"Text","Titel":"Title","Typ":"Type","Übernehmen":"Accept","Überschrift":"Header","Uhrzeit":"Time","Um die Veranstaltung sichtbar zu machen, wählen Sie den Punkt \"Sichtbarkeit\" im Administrationsbereich der Veranstaltung.":"In order to enable visibility of the course, please choose the tab \"visibility\" in the administration area of the course.","Untertitel":"Subtitle","URL":"URL","Veranstaltung berücksichtigen":"Regard course","Veranstaltung nicht berücksichtigen":"Do not regard course","Veranstaltungen":"Courses","Veranstaltungsdetails":"Course details","Versteckte Veranstaltungen können über die Suchfunktionen nicht gefunden werden.":"Hidden courses cannot be found via the search feature.","von":"from","Vorlage":"Template","weiter":"continue","Wert":"Value","Zeit":"Time","Zum Hauptordner":"Go to main folder","zurück":"back","Zurück":"Back","Zurücksetzen":"Reset","Zweck":"Purpose"}
\ No newline at end of file
This diff is collapsed.
File deleted
This diff is collapsed.
#!/bin/sh
#
# STEP 1:
# extract all Stud.IP message strings and merge them with the existing translations
#
LOCALE_RELATIVE_PATH="."
TRANSLATIONFILES_RELATIVE_PATHS="../public ../lib ../config ../cli ../templates ../app"
for language in en
do
test -f "$LOCALE_RELATIVE_PATH/$language/LC_MESSAGES/studip.po" && mv "$LOCALE_RELATIVE_PATH/$language/LC_MESSAGES/studip.po" "$LOCALE_RELATIVE_PATH/$language/LC_MESSAGES/studip.po.old"
> "$LOCALE_RELATIVE_PATH/$language/LC_MESSAGES/studip.pot"
find $TRANSLATIONFILES_RELATIVE_PATHS \( -iname "*.php" -o -iname "*.ihtml" \) -a \( ! -path "*/public/plugins_packages/*" -o -path "*/public/plugins_packages/core/*" \) | xargs xgettext --from-code=utf-8 -j -n --language=PHP -o "$LOCALE_RELATIVE_PATH/$language/LC_MESSAGES/studip.pot"
test -f "$LOCALE_RELATIVE_PATH/$language/LC_MESSAGES/studip.po.old" && msgmerge "$LOCALE_RELATIVE_PATH/$language/LC_MESSAGES/studip.po.old" "$LOCALE_RELATIVE_PATH/$language/LC_MESSAGES/studip.pot" --output-file="$LOCALE_RELATIVE_PATH/$language/LC_MESSAGES/studip.po"
done
......@@ -35,6 +35,7 @@ Vue.use(Router);
Vue.use(PortalVue);
function createApp(options, ...args) {
Vue.config.language = getLocale();
return new Vue({ store, ...options }, ...args);
}
......
import { translate } from 'vue-gettext';
import defaultTranslations from '../../../locales/de_DE.json';
import defaultTranslations from '../../../../locale/de/LC_MESSAGES/js-resources.json';
import eventBus from './event-bus.js';
const DEFAULT_LANG = 'de_DE';
......@@ -80,7 +80,8 @@ function getInstalledLanguages() {
async function getTranslations(locale) {
try {
const translation = await import(`../../../locales/${locale}.json`);
const language = locale.split(/[_-]/)[0];
const translation = await import(`../../../../locale/${language}/LC_MESSAGES/js-resources.json`);
return translation;
} catch (exception) {
......
{
" Dieser Filter enthält keine (neuen) Personen.": "This selection contains no (new) users.",
"%s hat geschrieben:": "%s wrote:",
"<%= count %> ausgewählt": "<%= count %> selected",
"Abschicken": "Submit",
"AbschlussKategorie suchen": "search degree category",
"Aktionen": "Actions",
"Alle Bereiche werden dann nach \"Allgemein\" verschoben!": "All areas will be moved to the category \"general\"!",
"Alle Räume anzeigen": "Show all rooms.",
"Alle entfernen": "Remove all",
"Alle hinzufügen": "Add all",
"Anmelderegel konfigurieren": "Configure admission setting",
"Anonym": "Anonymous",
"Apr": "Apr",
"April": "April",
"Aug": "Aug",
"August": "August",
"ausgewählt": "selected",
"Autor/-in": "Author",
"Bearbeiten.": "Edit.",
"Bedingung konfigurieren": "Configure condition",
"Beitrag verschieben": "Move post",
"Bild %u von %u": "Image %u of %u",
"Bitte %u Zeichen mehr eingeben": "Please enter %u more characters",
"Bitte %u Zeichen weniger eingeben": "Please enter %u characters less",
"Bitte bestätigen Sie die Aktion": "Please confirm action",
"Bitte geben Sie Ihren tatsächlichen Nachnamen an.": "Please enter your real last name.",
"Bitte geben Sie Ihren tatsächlichen Vornamen an.": "Please enter your real first name.",
"Bitte laden Sie die Seite neu, um fortzufahren": "To continue, please reload the page",
"Bitte wählen Sie einen gültigen Wert aus!": "Please specify a valid value!",
"Blenden Sie die restlichen Termine aus": "Hide remaining dates",
"Blenden Sie die restlichen Termine ein": "Show the remaining dates",
"Das Aktivieren des WYSIWYG Editors ist fehlgeschlagen.": "Activation of WYSIWYG editor failed.",
"Das Herunterladen dieser Datei ist nur eingeschränkt möglich.": "The download of this file is restricted.",
"Das Passwort ist zu kurz. Es sollte mindestens 8 Zeichen lang sein.": "The password is too short. It should have at least 8 characters.",
"Das Passwort stimmt nicht mit dem Bestätigungspasswort überein!": "Password and re-typed password don't match!",
"Datei hochladen": "Upload file",
"Datei ist zu groß oder hat eine nicht erlaubte Endung.": "The file is too big or it doesn't have an allowed extension.",
"Datum": "Date",
"Der Benutzername enthält unzulässige Zeichen, er darf keine Sonderzeichen oder Leerzeichen enthalten.": "There are invalid characters in the username - it must not contain any special characters nor space characters.",
"Der Benutzername ist zu kurz, er sollte mindestens 4 Zeichen lang sein.": "The username is too short - it must comprise at least 4 characters.",
"Detaillierte Veranstaltungsliste": "Detailed list of courses",
"Dez": "Dec",
"Dezember": "December",
"Di": "Tue.",
"Dialog wird geladen...": "Loading dialogue...",
"Die E-Mail-Adresse ist nicht korrekt!": "Invalid e-mail address!",
"Die Person ist bereits eingetragen.": "This person is already enroled.",
"Die Seite muss danach neu geladen werden, um den WYSIWYG Editor zu laden.": "The page must be reloaded afterwards to load the WYSIWYG editor.",
"Die Senderin/der Sender dieser Nachricht möchte Sie auf den folgenden Beitrag aufmerksam machen. ": "The sender of this message wants to call your attention to the following posting.",
"Die beiden Werte \"$1\" und \"$2\" stimmen nicht überein. ": "Values \"$1\" and \"$2\" are not identical.",
"Dienstag": "Tuesday",
"Dieser Ordner ist leer": "This folder is empty",
"Dieses Bild wird verkleinert dargestellt. Klicken Sie für eine größere Darstellung.": "Preview size. Click to enlarge.",
"Do": "Thu.",
"Dokument hinzufügen": "Add document",
"Dokument suchen": "Search document",
"Donnerstag": "Thursday",
"Downloads": "Downloads",
"Es werden auch alle Beiträge in diesem Bereich gelöscht!": "All postings in this area will be deleted as well!",
"Es wurden keine neuen Ergebnisse für \"<%= needle %>\" gefunden.": "No results were found for \"<%= needle %>\".",
"Fachsemester auswählen (optional)": "Select semester of study (optional)",
"Feb": "Feb",
"Februar": "February",
"Fehler bei der Übertragung": "An error occurred during the transmission",
"Fehler beim Aufruf des News-Controllers": "Error accessing the news controller",
"Fehler beim Aufruf des Tour-Controllers": "Error accessing the tour controller",
"Fehler": "Error",
"Fr": "Fri.",
"Freitag": "Friday",
"Füllen Sie noch die rot markierten Stellen korrekt aus.": "Fill in the red marked areas correctly.",
"Gefundene Nutzer": "Users found",
"Größe": "Size",
"HH:mm": "HH:mm",
"Hervorhebung aufheben": "Delete mark",
"Hierauf antworten.": "Reply on this.",
"hinzufügen": "add",
"Ihre Eingaben wurden bislang noch nicht gespeichert.": "Your input has not been saved yet.",
"Ja": "Yes",
"Jan": "Jan",
"Januar": "January",
"Jetzt": "Now",
"Jul": "Jul",
"Juli": "July",
"Jun": "Jun",
"Juni": "June",
"Kein Ergebnis gefunden.": "No results.",
"Keine Angabe beim Fach": "Not specified for field of study",
"Keine weitere Auswahl möglich": "No further selection possible",
"Keine Übereinstimmungen gefunden": "No match found",
"Kommentar schreiben. Enter zum Abschicken.": "Write comment. Press enter to send it.",
"Konnte die Konversation nicht laden. Probieren Sie es nachher erneut.": "Could not load the conversation. Please try again later.",
"Konnte die Suche nicht ausführen. Probieren Sie es nachher erneut.": "Could not execute the search. Please try again later.",
"Lade mehr Ergebnisse...": "Load more results...",
"Link wurde kopiert": "Link has been copied",
"Link zum Beitrag: ": "Link to posting:",
"Mai": "May",
"Mi": "Wed.",
"Mikrosekunde": "Microsecond",
"Millisekunde": "Millisecond",
"Minute": "minute",
"Mittwoch": "Wednesday",
"Mo": "Mon.",
"Modul suchen": "Search for module",
"Montag": "Monday",
"Mär": "Mar",
"März": "March",
"nachm.": "PM",
"Nachricht schreiben. Enter zum Abschicken.": "Write message. Press enter to send it.",
"Name": "Name",
"Nein": "No",
"Neu laden": "Reload",
"Neuen Termin eintragen": "Create new date",
"Nicht buchbare Räume:": "Non-allocatable rooms:",
"Noch nicht komplett ausgefüllt.": "Not yet filled in completely.",
"Nov": "Nov",
"November": "November",
"Nur buchbare Räume anzeigen": "Display bookable rooms only",
"oder": "or",
"Okt": "Oct",
"Oktober": "October",
"Optional weitere Studiengangteile (max. 5)": "Optional additional components (max. 5)",
"Sa": "Sat.",
"Samstag": "Saturday",
"Schließen": "Close",
"Schreib was, frag was. Enter zum Abschicken.": "Write something, ask something. Press enter to send it.",
"Sekunde": "Second",
"Sep": "Sep",
"September": "September",
"Sie haben <%= count %> Personen ausgewählt": "You selected <%= count %> persons",
"Sie haben nicht angegeben, wer die Nachricht empfangen soll!": "You did not specify who should receive the message!",
"Sie haben noch keine Anmelderegeln festgelegt.": "You haven't yet defined any admission rule.",
"Sie haben noch niemanden hinzugefügt.": "No-one added yet",
"Sie können nur %u Eintrag auswählen": "You may only select %u entry",
"Sie können nur %u Einträge auswählen": "You may only select %u entries",
"Sie sind nicht mehr im System angemeldet.": "You are no longer logged in.",
"Sind Sie sicher, dass Sie die regelmäßige Zeit ändern möchten?": "Are you sure to change the periodic course appointments?",
"Sind sie sicher, dass Sie diese Kategorie entfernen möchten? ": "Are you sure to delete this category?",
"Sind sie sicher, dass Sie diesen Bereich löschen möchten? ": "Are you sure to delete this area?",
"Sind sie sicher, dass Sie ihren bisherigen Beitrag verwerfen wollen?": "Do really want to discard your posting?",
"Smileys": "Smileys",
"So": "Sun.",
"Soll der WYSIWYG Editor aktiviert werden?": "Do you want to activate the WYSIWYG editor?",
"Soll die ausgewählte Berechtigung wirklich entfernt werden?": "Do you really want to delete the selected permission?",
"Sonntag": "Sunday",
"Starte die Konversation jetzt!": "Start the conversation now!",
"Status": "Status",
"Studiengang suchen": "Search course of study",
"Studiengangteil suchen": "Search course of study. ",
"Stunde": "hour",
"Suche zurücksetzen": "Reset search",
"Suche...": "Searching...",
"Suchergebnisse": "Search results",
"Termindetails bearbeiten": "Edit date details",
"Thema hervorheben": "Mark topic",
"Thema schließen": "Close topic",
"Thema öffnen": "Open topic",
"Typ": "Type",
"URL": "URL",
"Veranstaltung berücksichtigen": "Regard course",
"Veranstaltung nicht berücksichtigen": "Do not regard course",
"Veranstaltungsdetails": "Course details",
"Veranstaltungstyp auswählen (optional)": "Select course type (optional)",
"Vor": "Before",
"vorm.": "AM",
"Vor %s Minuten": "%s minutes ago",
"Wenn Sie die Seite verlassen, gehen ihre Änderungen verloren!": "If you leave the page your changes will be lost!",
"Wird geladen": "Loading",
"Wirklich %s Nachrichten löschen?": "Delete message %s?",
"Wollen Sie die Aktion wirklich ausführen?": "Do you really want to execute this action?",
"Wollen Sie die gewünschten Termine wirklich löschen?": "Do you really want to delete the selected dates?",
"Wollen Sie die im Plan gezeigten Anfragen wirklich buchen?": "Do you really want to book the request shown in the plan?",
"Wollen Sie diesen Filter wirklich entfernen?": "Are you sure to delete this filter?",
"Zeichen verbleibend: ": "Remaining characters:",
"Zeit wählen": "Select time",
"Zeit": "Time",
"Zeitzone": "Timezone",
"Zitat einfügen": "Insert quote",
"Zitat löschen": "Delete quote",
"Zitat teilen": "Share quote",
"Zum Hauptordner": "Go to main folder",
"Zur Diskussion": "Go to discussion",
"Zur Gesamtübersicht": "Back to overview",
"Zurück": "Back"
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment