They came from the phone's locale, so a phone set to Spanish showed "Octubre 2026" with an English interface (and I18nTest failed on any machine not set to English). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
232 lines
14 KiB
Java
232 lines
14 KiB
Java
package org.gingercal;
|
|
|
|
import java.text.DateFormatSymbols;
|
|
import java.text.SimpleDateFormat;
|
|
import java.util.Calendar;
|
|
import java.util.Date;
|
|
import java.util.HashMap;
|
|
import java.util.Locale;
|
|
import java.util.Map;
|
|
|
|
/**
|
|
* Interface language. English text is the key; Galician comes from the table below.
|
|
* Android 2.3 ships no Galician locale data, so month and weekday names live here too.
|
|
* tools/check_i18n.py checks that every L.t()/L.f() key has a translation with matching
|
|
* placeholders.
|
|
*/
|
|
public final class L {
|
|
private L() {}
|
|
|
|
/** Galician on (the app default); the desktop tests run in English. */
|
|
public static volatile boolean gl;
|
|
|
|
private static final Map<String, String> GL = new HashMap<String, String>();
|
|
|
|
public static String t(String en) {
|
|
if (!gl) return en;
|
|
String v = GL.get(en);
|
|
return v == null ? en : v;
|
|
}
|
|
|
|
public static String f(String en, Object... args) {
|
|
return String.format(Locale.US, t(en), args);
|
|
}
|
|
|
|
// ------------------------------------------------------------------ dates
|
|
|
|
static final String[] GL_MONTHS = {"xaneiro", "febreiro", "marzo", "abril", "maio", "xuño", "xullo",
|
|
"agosto", "setembro", "outubro", "novembro", "decembro"};
|
|
static final String[] GL_MONTHS_SHORT = {"xan", "feb", "mar", "abr", "mai", "xuñ", "xul", "ago", "set",
|
|
"out", "nov", "dec"};
|
|
static final String[] GL_DAYS = {"", "domingo", "luns", "martes", "mércores", "xoves", "venres", "sábado"};
|
|
static final String[] GL_DAYS_SHORT = {"", "dom", "lun", "mar", "mér", "xov", "ven", "sáb"};
|
|
|
|
public static DateFormatSymbols symbols() {
|
|
if (!gl) return new DateFormatSymbols(Locale.US); // English names, whatever the phone's language
|
|
DateFormatSymbols s = new DateFormatSymbols(Locale.US);
|
|
s.setMonths(GL_MONTHS);
|
|
s.setShortMonths(GL_MONTHS_SHORT);
|
|
s.setWeekdays(GL_DAYS);
|
|
s.setShortWeekdays(GL_DAYS_SHORT);
|
|
s.setAmPmStrings(new String[] {"a.m.", "p.m."});
|
|
return s;
|
|
}
|
|
|
|
public static SimpleDateFormat df(String pattern) {
|
|
return new SimpleDateFormat(pattern, symbols());
|
|
}
|
|
|
|
/** "Outubro de 2026" / "October 2026". */
|
|
public static String monthTitle(long t) {
|
|
String s = df(gl ? "MMMM 'de' yyyy" : "MMMM yyyy").format(new Date(t));
|
|
return s.length() > 0 ? Character.toUpperCase(s.charAt(0)) + s.substring(1) : s;
|
|
}
|
|
|
|
public static int firstDayOfWeek() {
|
|
return gl ? Calendar.MONDAY : Calendar.getInstance().getFirstDayOfWeek();
|
|
}
|
|
|
|
// ------------------------------------------------------------ translations
|
|
|
|
private static void put(String en, String gal) {
|
|
GL.put(en, gal);
|
|
}
|
|
|
|
static {
|
|
// main screen
|
|
put("Not set up yet: press Menu > Settings.", "Aínda sen configurar: preme Menú > Configuración.");
|
|
put("Syncing…", "Sincronizando…");
|
|
put("Loading %s from the server…", "Cargando %s do servidor…");
|
|
put("Couldn't load this month: %s", "Non se puido cargar este mes: %s");
|
|
put("never", "nunca");
|
|
put("Sync failed: %s\nLast good sync: %s", "Erro de sincronización: %s\nÚltima sincronización correcta: %s");
|
|
put("Synced %s", "Sincronizado: %s");
|
|
put("No upcoming events. Menu > New event, or Menu > Sync.", "Non hai eventos próximos. Menú > Novo evento ou Menú > Sincronizar.");
|
|
put("Nothing on %s. Long-press a day to add an event.", "Non hai nada o %s. Mantén premido un día para engadir un evento.");
|
|
put("View", "Vista");
|
|
put("Agenda", "Axenda");
|
|
put("Month", "Mes");
|
|
put("New event", "Novo evento");
|
|
put("Sync", "Sincronizar");
|
|
put("Today", "Hoxe");
|
|
put("Calendars", "Calendarios");
|
|
put("Settings", "Configuración");
|
|
put("Sync first: no writable calendar yet.", "Sincroniza primeiro: aínda non hai ningún calendario con permiso de escritura.");
|
|
put("Calendar: %s", "Calendario: %s");
|
|
put("Repeating event: edit the series in Nextcloud. Delete removes the whole series.", "Evento periódico: edita a serie en Nextcloud. Eliminar borra a serie completa.");
|
|
put("(no title)", "(sen título)");
|
|
put("(repeats)", "(repítese)");
|
|
put("Close", "Pechar");
|
|
put("Edit", "Editar");
|
|
put("Delete", "Eliminar");
|
|
put("Delete event?", "Eliminar o evento?");
|
|
put("This deletes EVERY occurrence of \"%s\".", "Isto elimina TODAS as repeticións de «%s».");
|
|
put("\"%s\" will be deleted on the server.", "«%s» eliminarase no servidor.");
|
|
put("Cancel", "Cancelar");
|
|
put("Deleting…", "Eliminando…");
|
|
put("Delete failed", "Non se puido eliminar");
|
|
put("OK", "Aceptar");
|
|
|
|
// dates and times
|
|
put("Today · %s", "Hoxe · %s");
|
|
put("Tomorrow · %s", "Mañá · %s");
|
|
put("All day", "Todo o día");
|
|
put("All day, until %s", "Todo o día, ata o %s");
|
|
put("No reminder", "Sen aviso");
|
|
put("At start time", "Á hora de comezo");
|
|
put("%d min before", "%d min antes");
|
|
put("%d h before", "%d h antes");
|
|
put("%d day before", "%d día antes");
|
|
|
|
// event editor
|
|
put("Edit event", "Editar evento");
|
|
put("Title", "Título");
|
|
put("Starts", "Comeza");
|
|
put("Ends", "Remata");
|
|
put("Location", "Lugar");
|
|
put("Notes", "Notas");
|
|
put("Save", "Gardar");
|
|
put("Alarm: %s", "Aviso: %s");
|
|
put("Alarm (saved in the event)", "Aviso (gárdase no evento)");
|
|
put("Calendar", "Calendario");
|
|
put("The end is before the start.", "O final é anterior ao comezo.");
|
|
put("No writable calendar. Sync first.", "Non hai ningún calendario con permiso de escritura. Sincroniza primeiro.");
|
|
put("Loading…", "Cargando…");
|
|
put("Can't load event", "Non se puido cargar o evento");
|
|
put("Repeating event", "Evento periódico");
|
|
put("Repeating events can't be edited on the phone yet. Edit the series in Nextcloud.", "Os eventos periódicos aínda non se poden editar no teléfono. Edita a serie en Nextcloud.");
|
|
put("Can't edit", "Non se pode editar");
|
|
put("The server returned no event data.", "O servidor non devolveu os datos do evento.");
|
|
put("Saving…", "Gardando…");
|
|
put("Not saved", "Non se gardou");
|
|
put("Saved", "Gardado");
|
|
|
|
// calendars
|
|
put("No calendars yet. Set up the account in Settings and sync.", "Aínda non hai calendarios. Configura a conta en Configuración e sincroniza.");
|
|
put("(read-only)", "(só lectura)");
|
|
put("first writable", "o primeiro con escritura");
|
|
put("New events go to: %s", "Os eventos novos gárdanse en: %s");
|
|
put("Default calendar", "Calendario predeterminado");
|
|
|
|
// settings
|
|
put("Calendar Lite settings", "Configuración de Calendar Lite");
|
|
put("Nextcloud server: your normal https:// address. This app brings its own modern TLS, so no bridge is needed, at home or away. Use an app password, not your real one.",
|
|
"Servidor Nextcloud: o teu enderezo https:// de sempre. Esta aplicación trae o seu propio TLS moderno, así que non fai falta ningunha ponte, nin na casa nin fóra. Usa un contrasinal de aplicación, non o teu contrasinal real.");
|
|
put("Server address", "Enderezo do servidor");
|
|
put("User name", "Usuario");
|
|
put("App password", "Contrasinal de aplicación");
|
|
put("Pinned certificate SHA-256 (filled in for you)", "SHA-256 do certificado fixado (énchese automaticamente)");
|
|
put("optional", "opcional");
|
|
put("Days ahead to sync", "Días futuros que sincronizar");
|
|
put("Save and test connection", "Gardar e probar a conexión");
|
|
put("Re-download everything", "Descargar todo de novo");
|
|
put("Background sync", "Sincronización automática");
|
|
put("Background sync: %s", "Sincronización automática: %s");
|
|
put("Manual only", "Só manual");
|
|
put("Every hour", "Cada hora");
|
|
put("Every %d hours", "Cada %d horas");
|
|
put("Phone notification", "Notificación no teléfono");
|
|
put("Notification: %s", "Notificación: %s");
|
|
put("Off", "Desactivada");
|
|
put("off", "desactivada");
|
|
put("Language: %s", "Lingua: %s");
|
|
put("Re-downloading in the background", "Descargando todo de novo en segundo plano");
|
|
put("Server address and user name are required.", "O enderezo do servidor e o usuario son obrigatorios.");
|
|
put("Unencrypted connection", "Conexión sen cifrar");
|
|
put("http:// sends your password in clear text over the internet. Use the https:// address instead, or only use http:// to a LAN address.",
|
|
"Con http:// o contrasinal viaxa sen cifrar por internet. Usa o enderezo https://, ou usa http:// só cun enderezo da rede local.");
|
|
put("Use anyway", "Usar igualmente");
|
|
put("Connecting…", "Conectando…");
|
|
put("Connection failed", "Erro de conexión");
|
|
put("Connected. Calendars found: %d\n", "Conectado. Calendarios atopados: %d\n");
|
|
put("It works", "Funciona");
|
|
put("Sync now", "Sincronizar agora");
|
|
|
|
// certificate trust
|
|
put("WARNING: the server certificate changed since you trusted it. That happens when a self-signed certificate is regenerated - or when someone is intercepting the connection.\n\n",
|
|
"AVISO: o certificado do servidor cambiou desde que confiaches nel. Isto pasa se se rexenera un certificado autoasinado, ou se alguén está a interceptar a conexión.\n\n");
|
|
put("The server certificate isn't signed by a known authority (normal for a self-signed server or an old TLS 1.0 bridge).\n\n",
|
|
"O certificado do servidor non está asinado por unha autoridade coñecida (é normal nun servidor autoasinado ou nunha ponte TLS 1.0 antiga).\n\n");
|
|
put("Subject: %s\nIssuer: %s\nExpires: %s\n\nSHA-256:\n%s\n\nOnly trust it if this matches the fingerprint printed on your server.",
|
|
"Suxeito: %s\nEmisor: %s\nCaduca: %s\n\nSHA-256:\n%s\n\nConfía nel só se coincide coa pegada dixital que mostra o teu servidor.");
|
|
put("Certificate changed!", "O certificado cambiou!");
|
|
put("Trust this certificate?", "Confiar neste certificado?");
|
|
put("Trust", "Confiar");
|
|
put("Interrupted", "Interrompido");
|
|
put("The server certificate is for a different address (%1$s).", "O certificado do servidor é doutro enderezo (%1$s).");
|
|
put("The server certificate has expired, or the phone's date is wrong.", "O certificado do servidor caducou ou a data do teléfono é incorrecta.");
|
|
put("Server certificate changed (does not match the pinned fingerprint)", "O certificado do servidor cambiou (non coincide coa pegada fixada)");
|
|
put("Server certificate is not trusted by this phone", "Este teléfono non confía no certificado do servidor");
|
|
|
|
// errors
|
|
put("Can't resolve %s. No connection, or a typo in the server address.", "Non se pode resolver %s. Non hai conexión ou hai un erro no enderezo do servidor.");
|
|
put("Can't connect to the server (%s). Wrong address or port, or the server is down?",
|
|
"Non se pode conectar co servidor (%s). Enderezo ou porto incorrecto, ou servidor caído?");
|
|
put("The server took too long to answer.", "O servidor tardou de máis en responder.");
|
|
put("TLS error: %s", "Erro TLS: %s");
|
|
put("Network error: %s", "Erro de rede: %s");
|
|
put("Out of memory. Lower 'Days ahead' in Settings.", "Sen memoria. Reduce «Días futuros» na configuración.");
|
|
put("Error: %s", "Erro: %s");
|
|
put("Login refused (401). Check the user name and use a Nextcloud app password (Settings > Security > Devices & sessions).",
|
|
"Acceso rexeitado (401). Comproba o usuario e usa un contrasinal de aplicación de Nextcloud (Configuración > Seguranza > Dispositivos e sesións).");
|
|
put("Not allowed to write to this calendar (403). It may be read-only/shared.", "Non tes permiso para escribir neste calendario (403). Pode ser de só lectura ou compartido.");
|
|
put("Too many redirects from the server.", "O servidor fixo demasiadas redireccións.");
|
|
put("The server redirected to %s, not the address set in the app. Put that address in Settings.",
|
|
"O servidor redirixiu a %s, que non é o enderezo configurado na aplicación. Pon ese enderezo na configuración.");
|
|
put("Redirect loop (HTTP %d back to the same address). Use the server's https:// address in Settings.",
|
|
"Bucle de redirección (HTTP %d ao mesmo enderezo). Usa o enderezo https:// do servidor na configuración.");
|
|
put("%s %s failed: HTTP %d%s", "%s %s fallou: HTTP %d%s");
|
|
put(" (not found)", " (non atopado)");
|
|
put(" (not a WebDAV URL?)", " (non é un URL WebDAV?)");
|
|
put("Server did not report a CalDAV principal", "O servidor non informou de ningún principal CalDAV");
|
|
put("Could not load event: HTTP %d", "Non se puido cargar o evento: HTTP %d");
|
|
put("Saving failed: HTTP %d", "Non se puido gardar: HTTP %d");
|
|
put("Event was changed on the server meanwhile. Sync and try again.", "O evento cambiou no servidor mentres tanto. Sincroniza e téntao de novo.");
|
|
put("Delete failed: HTTP %d", "Non se puido eliminar: HTTP %d");
|
|
put("Bad XML from server: %s", "XML incorrecto do servidor: %s");
|
|
put("Empty XML from server", "XML baleiro do servidor");
|
|
put("%d calendars: %d refreshed (%d events)", "Calendarios: %d, actualizados: %d (eventos: %d)");
|
|
put(", %d unchanged", ", sen cambios: %d");
|
|
}
|
|
}
|