You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
113 lines
4.0 KiB
113 lines
4.0 KiB
#!/usr/bin/env ruby |
|
# frozen_string_literal: true |
|
|
|
# SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL |
|
# SPDX-FileCopyrightText: 2021 Harald Sitter <sitter@kde.org> |
|
|
|
# Generates timezone tables out of tzdata.zi backing data such that the pretty names may be translated. |
|
|
|
require 'erb' |
|
require 'ostruct' |
|
|
|
# Wraps template rendering. Templating is implemented using the ERB template system. |
|
class Template |
|
def self.render(context) |
|
erb = ERB.new(File.read("#{__dir__}/timezonesi18n_generated.h.erb")) |
|
erb.result(context.instance_eval { binding }) |
|
end |
|
end |
|
|
|
# Context object for template rendering. Inside the template file anything defined in here may be used. |
|
# For simplicity's sake continents and cities are not modeled as fully functional objects but rather use |
|
# this context wrapper. Slightly less code. |
|
class RenderContext < OpenStruct |
|
def initialize(continents:, cities:) |
|
super |
|
end |
|
|
|
def city_description(city) |
|
return 'This is a generic time zone name, localize as needed' if city.start_with?('UTC') |
|
|
|
'This is a city associated with particular time zone' |
|
end |
|
|
|
def continent_description(_continent) |
|
'This is a continent/area associated with a particular timezone' |
|
end |
|
|
|
# prettify city name |
|
def to_city_name(city) |
|
city = city.tr('_', ' ') |
|
{ |
|
'DumontDUrville' => 'Dumont d’Urville', |
|
'ComodRivadavia' => 'Comodoro Rivadavia' |
|
# TODO do we want these? seeing as different transliterations are in use, one is just as bad as the other, surely |
|
# 'Uzhgorod' => 'Uzhhorod' # the tz has the legacy transliteration |
|
# 'Zaporozhye' => 'Zaporizhzhia' |
|
# 'Kiev' => 'Kyiv' |
|
}.fetch(city, city) |
|
end |
|
|
|
# prettify continent name |
|
def to_contient_name(continent) |
|
continent # leave unchanged, they are all lovely |
|
end |
|
end |
|
|
|
raise 'tzdata.zi missing, your tzdata was possibly built without' unless File.exist?('/usr/share/zoneinfo/tzdata.zi') |
|
|
|
data = File.read('/usr/share/zoneinfo/tzdata.zi') |
|
|
|
continents = [] |
|
cities = [] |
|
data.split("\n").each do |line| |
|
line = line.strip |
|
next if line[0] == '#' # comment |
|
|
|
# zi files have a tricky format. only look at lines that make sense for us (Zone entries and Link entries) |
|
is_zone = line[0].downcase == 'z' |
|
is_link = line[0].downcase == 'l' |
|
next unless is_zone || is_link |
|
|
|
line_parts = line.split(' ') |
|
|
|
# Since we have 2 line formats, the location of the timezone is different in each |
|
tz = is_zone ? line_parts[1] : line_parts[2] |
|
parts = tz.split('/') |
|
|
|
# some links are fishy single names we can't use (e.g. `L Europe/Warsaw Poland`) |
|
next if parts.size < 2 |
|
|
|
continent = parts[0] |
|
|
|
# some links also have fake continent values (e.g. `L America/Denver SystemV/MST7MDT`) followed by regions therein |
|
next if %w[systemv us etc canada brazil mexico chile].any? { |x| x == continent.downcase } |
|
|
|
city = parts[-1] |
|
|
|
# some links are simply pointing at directions within a region/country |
|
next if %w[north east south west].any? { |x| x == city.downcase } |
|
# some links are abbreviations (e.g. `Australia/NSW` for new south wales) |
|
# Australia has some more links for regions but we'd have to filter them individually and I can't be bothered. |
|
next if city.size <= 3 && city.upcase == city |
|
# some are Knox and also known as Knox_IN for reasons |
|
next if city == 'Knox_IN' |
|
|
|
continents << continent |
|
cities << city |
|
end |
|
|
|
# make sure fake cities exist |
|
(0..14).each do |i| |
|
cities << format('UTC+%02d:00', i) |
|
cities << format('UTC-%02d:00', i) |
|
end |
|
# The partial hours are from original code this script was built based on. They do not actually correspond to timezone |
|
# links though, so I'm not sure how they work but keep them regardless since I hope there's magic going on somehwere. |
|
cities += %w[UTC UTC+03:30 UTC+04:30 UTC+05:30 UTC+05:45 UTC+06:30 UTC+09:30 UTC-03:30 UTC-04:30] |
|
|
|
cities = cities.sort_by(&:downcase).uniq |
|
continents = continents.sort_by(&:downcase).uniq |
|
|
|
data = Template.render(RenderContext.new(cities: cities, continents: continents)) |
|
File.write("#{__dir__}/timezonesi18n_generated.h", data)
|
|
|