/* -*- Mode: JS2; indent-tabs-mode: nil; js2-basic-offset: 4 -*- */
/* vim: set et ts=4 sw=4: */
/*
* Copyright (c) 2014 Marcus Lundblad
*
* GNOME Maps is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* GNOME Maps is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with GNOME Maps; if not, see .
*
* Author: Marcus Lundblad
*/
import gettext from 'gettext';
const _ = gettext.gettext;
const C_ = gettext.dgettext;
import GLib from 'gi://GLib';
import * as Time from './time.js';
import * as Utils from './utils.js';
/* Translate an opening time specification tag value.
* from OSM into a "two-dimensional" (array-of-arrays) grid of human-readable
* strings (marked for translation) suitable for laying out in aligned rows
* and columns in a GtkGrid in the place bubbles.
*
* Some limitations are imposed to keep the translations manageable:
* A maximum of three components (separated by ; in the tag) are considered.
* For each component a maximum of three day intervals are considered.
* Each day interval can have one or two time intervals specified.
* For each of these limitations, the input string is passed on unmodified
* if the format is outside the supported cases, so no data should be dropped.
* Currently only specifying weekdays and public and school holidays are
* supported.
* Other variants, such as month-specific opening hours and other interval
* variants are not currently supported. In these cases, the data is
* returned as-is.
*
* The definition for the opening_hours tag can be found at:
* http://wiki.openstreetmap.org/wiki/Key:opening_hours
*/
export function translateOpeningHours(string) {
if (string === '24/7' || string === 'Mo-Su 00:00-24:00' ||
string === '00:00-24:00')
return [[_("Around the clock")]];
else if (string === 'sunrise-sunset')
return [[_("From sunrise to sunset")]];
else {
/* split "components" */
let splitParts = string.split(';');
return splitParts.map(p => _translateOpeningHoursPart(p.trim()));
}
}
/*
* Parse a time range component, comprised of either a single time range, or
* day and time ranges, such as:
* 10:00-18:00
* 09:00-12:00,13:00-19:00
* Mo-Fr 10:00-19:00
* Mo-We,Fr 10:00-12:00,13:00-17:00
* Mo-We,Fr 10:00-12:00, 13:00-17:00
*/
export function _translateOpeningHoursPart(string) {
let splitString = string.split(/\s+/);
let len = splitString.length;
if (len === 1) {
return [_translateOpeningHoursTimeIntervalList(string.trim())];
} else if (len === 2 || len === 3) {
let dayIntervalSpec =
_translateOpeningHoursDayIntervalList(splitString[0].trim());
let intervalString =
len === 2 ? splitString[1].trim() :
splitString[1].trim() + splitString[2].trim();
let timeIntervalSpec =
_translateOpeningHoursTimeIntervalList(intervalString);
return [Utils.firstToLocaleUpperCase(dayIntervalSpec),
timeIntervalSpec];
} else {
// for an unknown format, just output the raw value
return [string];
}
}
/*
* Parse a day interval, such as:
* Mo-Fr
* Mo,We,Th-Fr
*/
export function _translateOpeningHoursDayIntervalList(string) {
let splitParts = string.split(',');
let interval1, interval2, interval3;
switch (splitParts.length) {
case 1:
return _translateOpeningHoursDayInterval(splitParts[0].trim());
case 2:
interval1 = _translateOpeningHoursDayInterval(splitParts[0].trim());
interval2 = _translateOpeningHoursDayInterval(splitParts[1].trim());
/* Translators:
* This represents a format string consisting of two day interval
* specifications.
* For example:
* Mo-Fr,Sa
* where the "Mo-Fr" and "Sa" parts are replaced by the %s
* place holder.
* The separator (,) could be replaced with a translated variant or
* a phrase if appropriate. */
return C_("day interval list", "%s,%s").format(interval1, interval2);
case 3:
interval1 = _translateOpeningHoursDayInterval(splitParts[0].trim());
interval2 = _translateOpeningHoursDayInterval(splitParts[1].trim());
interval3 = _translateOpeningHoursDayInterval(splitParts[2].trim());
/* Translators:
* This represents a format string consisting of three day interval
* specifications.
* For example:
* Mo-We,Fr,Su
* where the "Mo-We", "Fr", and "Su" parts are replaced by the
* %s place holder.
* The separator (,) could be replaced with a translated variant or
* a phrase if appropriate. */
return C_("day interval list", "%s,%s,%s").
format(interval1, interval2, interval3);
default:
// for other formats, just return the raw string
return string;
}
}
/*
* Parse a day interval consisting of either a single day
* or a range, such as:
* Mo-Fr
* Tu
*/
export function _translateOpeningHoursDayInterval(string) {
let splitString = string.split('-');
// special case: Mo-Su treated as "every day"
if (string === 'Mo-Su')
return _("Every day");
switch (splitString.length) {
case 1:
return _translateOpeningHoursDay(splitString[0].trim());
case 2:
let from = splitString[0].trim();
let to = splitString[1].trim();
/* Translators:
* This represents a range of days with a starting and ending day.
*/
return C_("day range", "%s-%s").format(
_translateOpeningHoursDay(from),
_translateOpeningHoursDay(to));
default:
// unknown format, just return the input
return string;
}
}
function _translateOpeningHoursDay(string) {
if (string === 'PH')
return _("Public holidays");
if (string === 'SH')
return _("School holidays");
// create a dummy DateTime instance which is guaranteed to be a Monday
let time = GLib.DateTime.new_local(1, 1, 1, 0, 0, 0.0);
let days = ['Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa', 'Su'];
for (let i = 0; i < days.length; i++) {
if (string === days[i]) {
time = time.add_days(i);
return time.format('%a');
}
}
// unknown value, just return the input
return string;
}
/*
* Parse a time interval list, such as:
* 10:00-20:00
* 10:00-12:00,13:00-17:00
*/
function _translateOpeningHoursTimeIntervalList(string) {
let splitString = string.split(',');
switch (splitString.length) {
case 1:
return _translateOpeningHoursTimeInterval(splitString[0].trim());
case 2:
let interval1 = splitString[0].trim();
let interval2 = splitString[1].trim();
/* Translators:
* This is a list with two time intervals, such as:
* 09:00-12:00, 13:00-14:00
* The intervals are represented by the %s place holders and
* appropriate white space or connected phrase could be modified by
* the translation. The order of the arguments can be rearranged
* using the %n$s syntax.
*/
return C_("time interval list", "%s, %s").format(
_translateOpeningHoursTimeInterval(interval1),
_translateOpeningHoursTimeInterval(interval2));
default:
// for other number of components, just return the input
return string;
}
}
/*
* Parse a time interval
*/
function _translateOpeningHoursTimeInterval(string) {
if (string === 'off')
return _("not open");
let splitString = string.split('-');
if (splitString.length == 2) {
let from = splitString[0].trim();
let to = splitString[1].trim();
/* Translators:
* This is a time interval with a starting and an ending time.
* The time values are represented by the %s place holders and
* appropriate white spacing or connecting phrases can be set by the
* translation as needed. The order of the arguments can be rearranged
* using the %n$s syntax.
*/
return C_("time interval", "%s-%s").format(
_translateOpeningHoursTime(from),
_translateOpeningHoursTime(to));
} else {
// unknown time interval format, just return the input
return string;
}
}
/*
* Parse a time.
*/
function _translateOpeningHoursTime(string) {
let splitString = string.split(':');
if (splitString.length == 2) {
let h = splitString[0];
let min = splitString[1];
// if the parts aren't numbers
if (h % 1 !== 0 || min % 1 !== 0)
return string;
// if the hours or minute components are out of range
if (h > 24 || h < 0 || min > 59 || min < 0)
return string;
return Time.formatTimeFromHoursAndMins(h, min);
} else {
// unknown format, just return input
return string;
}
}
export function translateReligion(string) {
switch(string) {
case 'animist': return _("Animism");
case 'bahai': return_("Bahá'í");
case 'buddhist': return _("Buddhism");
case 'caodaism': return _("Caodaism");
case 'christian': return _("Christianity");
case 'confucian': return _("Confucianism");
case 'hindu': return _("Hinduism");
case 'jain': return _("Jainism");
case 'jewish': return _("Judaism");
case 'muslim': return _("Islam");
case 'multifaith': return _("Multiple Religions");
case 'pagan': return _("Paganism");
case 'pastafarian': return _("Pastafarianism");
case 'scientologist': return _("Scientology");
case 'shinto': return _("Shinto");
case 'sikh': return _("Sikhism");
case 'spiritualist': return _("Spiritualism");
case 'taoist': return _("Taoism");
case 'unitarian_universalist': return _("Unitarian Universalism");
case 'voodoo': return _("Voodoo");
case 'yazidi': return _("Yazidism");
case 'zoroastrian': return _("Zoroastrianism");
default: return null;
}
}