1 /* Copyright (c) 2003-2014 Xfce Development Team
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor,
16 * Boston, MA 02110-1301, USA.
17 */
18
19 #ifdef HAVE_CONFIG_H
20 #include <config.h>
21 #endif
22
23 #include <string.h>
24 #include <time.h>
25
26 #include "weather-parsers.h"
27 #include "weather-data.h"
28 #include "weather.h"
29 #include "weather-translate.h"
30
31 #define DAY_LOC_N (sizeof(gchar) * 100)
32 #define NODATA "NODATA"
33
34
35 static const gchar *moon_phases[] = {
36 /* TRANSLATORS: Moon phases */
37 N_("New moon"),
38 N_("Waxing crescent"),
39 N_("First quarter"),
40 N_("Waxing gibbous"),
41 N_("Full moon"),
42 N_("Waning gibbous"),
43 N_("Third quarter"),
44 N_("Waning crescent"),
45 NULL
46 };
47 #define NUM_MOON_PHASES (sizeof(moon_phases) / sizeof(gchar *))
48
49 typedef struct {
50 gint id;
51 gchar *symbol;
52 gchar *desc;
53 gchar *night_desc;
54 } symbol_desc;
55
56 static const symbol_desc symbol_to_desc[] = {
57 /*
58 * TRANSLATORS: How these symbols are named and defined is explained at
59 * http://om.yr.no/forklaring/symbol/ and https://api.met.no/faq.html#symbols.
60 * To be more concise / shorter, the plugin uses names that deviate a bit from yr.no, so that
61 * they fit well in the tooltip, forecast tab etc.
62 *
63 * More information can be obtained from the following pages:
64 * http://www.theweathernetwork.com/weathericons/?product=weathericons&pagecontent=index
65 * http://www.theweathernetwork.com/index.php?product=help&placecode=cabc0164&pagecontent=helpicons
66 * http://www.mir-co.net/sonstiges/wetterausdruecke.htm
67 * The latter page is in German, but it contains a symbol table with Norwegian descriptions.
68 */
69 { 1, "SUN", N_("Sunny"), N_("Clear") },
70 { 2, "LIGHTCLOUD", N_("Lightly cloudy"), N_("Lightly cloudy") },
71 { 3, "PARTLYCLOUD", N_("Partly cloudy"), N_("Partly cloudy") },
72 { 4, "CLOUD", N_("Cloudy"), N_("Cloudy") },
73
74 /*
75 * http://www.theweathernetwork.com/weathericons/?product=weathericons&pagecontent=index:
76 * "Showers – Some sun is expected, interspersed with showers from
77 * time to time. As opposed to rain, showers describe liquid
78 * precipitation that can vary greatly in intensity over a short
79 * amount of time. [...] Precipitation may be locally heavy for
80 * short amounts of time."
81 */
82 { 5, "LIGHTRAINSUN", N_("Rain showers"), N_("Rain showers") },
83
84 /*
85 * http://www.theweathernetwork.com/weathericons/?product=weathericons&pagecontent=index:
86 * "Thunder Showers - Intermittent rain showers with thunder and lightning, generally
87 * short-lived."
88 */
89 { 6, "LIGHTRAINTHUNDERSUN", N_("Thunder showers"), N_("Thunder showers") },
90
91 /* Analogues to "Rain showers" */
92 { 7, "SLEETSUN", N_("Sleet showers"), N_("Sleet showers") },
93 { 8, "SNOWSUN", N_("Snow showers"), N_("Snow showers") },
94
95 /* It's raining, usually incessantly, but not heavily. */
96 { 9, "LIGHTRAIN", N_("Light rain"), N_("Light rain") },
97
98 /* Heavy, usually incessant rain. met.no now uses "heavy rain", but personally I find light
99 * rain and rain somewhat better. Symbol names indicate this is the way met.no did it some
100 * time ago. */
101 { 10, "RAIN", N_("Rain"), N_("Rain") },
102
103 { 11, "RAINTHUNDER", N_("Rain with thunder"), N_("Rain with thunder") },
104
105 /* Sleet is a mixture of rain and snow, but it's not hail. */
106 { 12, "SLEET", N_("Sleet"), N_("Sleet") },
107
108 { 13, "SNOW", N_("Snow"), N_("Snow") },
109
110 /*
111 * http://en.wikipedia.org/wiki/Thundersnow:
112 * "Thundersnow, also known as a winter thunderstorm or a thunder snowstorm, is a relatively
113 * rare kind of thunderstorm with snow falling as the primary precipitation instead of
114 * rain. It typically falls in regions of strong upward motion within the cold sector of an
115 * extratropical cyclone."
116 */
117 { 14, "SNOWTHUNDER", N_("Thundersnow"), N_("Thundersnow") },
118
119 { 15, "FOG", N_("Fog"), N_("Fog") },
120
121 /* Symbols 16-19 are used for polar days (unused beginning with API version 1.2) */
122 { 16, "SUN", N_("Sunny"), N_("Clear") },
123 { 17, "LIGHTCLOUD", N_("Lightly cloudy"), N_("Lightly cloudy") },
124 { 18, "LIGHTRAINSUN", N_("Rain showers"), N_("Rain showers") },
125 { 19, "SNOWSUN", N_("Snow showers"), N_("Snow showers") },
126
127 /* Same as symbols 1-15, but with thunder */
128 { 20, "SLEETSUNTHUNDER", N_("Sleet showers with thunder"), N_("Sleet showers with thunder") },
129 { 21, "SNOWSUNTHUNDER", N_("Snow showers with thunder"), N_("Snow showers with thunder") },
130 { 22, "LIGHTRAINTHUNDER", N_("Light rain with thunder"), N_("Light rain with thunder") },
131 { 23, "SLEETTHUNDER", N_("Sleet with thunder"), N_("Sleet with thunder") },
132 };
133
134 #define NUM_SYMBOLS (sizeof(symbol_to_desc) / sizeof(symbol_to_desc[0]))
135
136
137 /*
138 * API version 1.2, published in May 2014, introduced new symbols. We
139 * try to match these with existing symbols, in order to be compatible
140 * with existing icon themes and to maintain translation completeness.
141 *
142 * See https://api.met.no/weatherapi/weathericon/1.1/documentation
143 * for a list of symbols. For a list of symbols with descriptions,
144 * see http://om.yr.no/forklaring/symbol.
145 */
146 static gint
replace_symbol_id(gint id)147 replace_symbol_id(gint id)
148 {
149 /* Symbol ids greater than 100 are used for indicating polar
150 * night. These ids are over the ordinary id + 100. Since we
151 * don't support polar icons, we can simply subtract 100 to
152 * get the non-polar symbol ids.
153 */
154 if (id > 100)
155 id -= 100;
156
157 switch (id) {
158 case 24: return 22; /* Light rain showers and thunder */
159 case 25: return 6; /* Heavy rain showers and thunder */
160 case 26: return 20; /* Light sleet showers and thunder */
161 case 27: return 20; /* Heavy sleet showers and thunder */
162 case 28: return 21; /* Light snow showers and thunder */
163 case 29: return 21; /* Heavy snow showers and thunder */
164 case 30: return 22; /* Light rain and thunder */
165 case 31: return 23; /* Light sleet and thunder */
166 case 32: return 23; /* Heavy sleet and thunder */
167 case 33: return 14; /* Light snow and thunder */
168 case 34: return 14; /* Heavy snow and thunder */
169
170 /* symbols 35-39 are unused */
171
172 case 40: return 5; /* Light rain showers */
173 case 41: return 5; /* Heavy rain showers */
174 case 42: return 7; /* Light sleet showers */
175 case 43: return 7; /* Heavy sleet showers */
176 case 44: return 8; /* Light snow showers */
177 case 45: return 8; /* Heavy snow showers */
178 case 46: return 9; /* Light rain */
179 case 47: return 12; /* Light sleet */
180 case 48: return 12; /* Heavy sleet */
181 case 49: return 13; /* Light snow */
182 case 50: return 13; /* Heavy snow */
183 default: return id;
184 }
185 }
186
187
188 const gchar *
get_symbol_for_id(guint id)189 get_symbol_for_id(guint id)
190 {
191 if (G_UNLIKELY(id < 1))
192 return NODATA;
193
194 if (id >= NUM_SYMBOLS)
195 id = replace_symbol_id(id);
196
197 if (id < NUM_SYMBOLS)
198 return symbol_to_desc[id-1].symbol;
199
200 return NODATA;
201 }
202
203
204 const gchar *
translate_desc(const gchar * desc,const gboolean nighttime)205 translate_desc(const gchar *desc,
206 const gboolean nighttime)
207 {
208 guint i;
209
210 for (i = 0; i < NUM_SYMBOLS; i++) {
211 if (!strcmp(desc, symbol_to_desc[i].symbol)) {
212 if (nighttime)
213 return _(symbol_to_desc[i].night_desc);
214 else
215 return _(symbol_to_desc[i].desc);
216 }
217 }
218 return desc;
219 }
220
221
222 const gchar *
translate_moon_phase(const gchar * moon_phase)223 translate_moon_phase(const gchar *moon_phase)
224 {
225 guint i;
226
227 for (i = 0; i < NUM_MOON_PHASES; i++) {
228 if (!strcmp(moon_phase, moon_phases[i])) {
229 return _(moon_phases[i]);
230 }
231 }
232 return moon_phase;
233 }
234
235
236 gchar *
translate_day(const gint weekday)237 translate_day(const gint weekday)
238 {
239 struct tm time_tm;
240 gchar *day_loc;
241 int len;
242
243 if (weekday < 0 || weekday > 6)
244 return NULL;
245
246 time_tm.tm_wday = weekday;
247
248 day_loc = g_malloc(DAY_LOC_N);
249
250 len = strftime(day_loc, DAY_LOC_N, "%A", &time_tm);
251 day_loc[len] = 0;
252 if (!g_utf8_validate(day_loc, -1, NULL)) {
253 gchar *utf8 = g_locale_to_utf8(day_loc, -1, NULL, NULL, NULL);
254 g_free(day_loc);
255 day_loc = utf8;
256 }
257
258 return day_loc;
259 }
260